Working with nested arrays is a common task in JavaScript. One frequent requirement is grouping objects by a specific property and calculating the average value for each group.
In this guide, we’ll explore the most effective way to group data and compute averages using modern JavaScript.
Example Problem
Suppose you have an array containing nested arrays of student scores:
const data = [
[
{ subject: 'Math', score: 80 },
{ subject: 'Science', score: 90 }
],
[
{ subject: 'Math', score: 70 },
{ subject: 'Science', score: 85 }
],
[
{ subject: 'Math', score: 95 }
]
];
The goal is to calculate the average score for each subject.
Expected output:
{
Math: 81.67,
Science: 87.5
}
Step 1: Flatten the Nested Arrays
The easiest way is to flatten the nested structure first.
const flattened = data.flat();
Result:
[
{ subject: 'Math', score: 80 },
{ subject: 'Science', score: 90 },
{ subject: 'Math', score: 70 },
{ subject: 'Science', score: 85 },
{ subject: 'Math', score: 95 }
]
Step 2: Group and Aggregate
Use reduce() to collect totals and counts.
const grouped = flattened.reduce((acc, item) => {
if (!acc[item.subject]) {
acc[item.subject] = {
total: 0,
count: 0
};
}
acc[item.subject].total += item.score;
acc[item.subject].count++;
return acc;
}, {});
Result:
{
Math: { total: 245, count: 3 },
Science: { total: 175, count: 2 }
}
Step 3: Calculate Averages
Convert totals into averages.
const averages = Object.fromEntries(
Object.entries(grouped).map(([subject, stats]) => [
subject,
stats.total / stats.count
])
);
console.log(averages);
Output:
{
Math: 81.66666666666667,
Science: 87.5
}
Complete Solution
const averages = Object.fromEntries(
Object.entries(
data.flat().reduce((acc, item) => {
if (!acc[item.subject]) {
acc[item.subject] = { total: 0, count: 0 };
}
acc[item.subject].total += item.score;
acc[item.subject].count++;
return acc;
}, {})
).map(([subject, stats]) => [
subject,
stats.total / stats.count
])
);
console.log(averages);
Formatting the Result
To display averages with two decimal places:
const formatted = Object.fromEntries(
Object.entries(averages).map(([key, value]) => [
key,
Number(value.toFixed(2))
])
);
console.log(formatted);
Output:
{
Math: 81.67,
Science: 87.50
}
Performance Considerations
For small and medium-sized datasets, using flat() and reduce() provides excellent readability.
For extremely large datasets, you may prefer a single-pass loop to avoid creating an intermediate flattened array. However, for most applications, the difference is negligible and the cleaner code is usually worth it.
Infographic

Conclusion
The best approach to group objects in nested arrays and calculate averages is to:
- Flatten the nested arrays using
flat(). - Group data with
reduce(). - Track totals and counts.
- Calculate averages using
Object.entries()andObject.fromEntries().
This approach is concise, easy to maintain, and works well with modern JavaScript applications.