Most efficient method to groupby on an array of objects - JavaScript

Grouping arrays of objects is a common task in JavaScript data processing. We'll explore efficient methods to group objects by single or multiple properties and aggregate values.

Sample Data

Let's start with an array of objects representing project phases, steps, and tasks:

const arr = [
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];

console.log("Original data:", arr.length, "records");
Original data: 8 records

Method 1: Using reduce() with Map (Most Efficient)

This method uses nested Maps to handle multiple grouping levels efficiently:

const groupBy = (array, groups, valueKey) => {
    const map = new Map();
    groups = [].concat(groups); // Ensure groups is always an array
    
    return array.reduce((acc, val) => {
        groups.reduce((accu, value, ind, { length }) => {
            let child;
            if (accu.has(val[value])) {
                return accu.get(val[value]);
            }
            
            if (ind + 1 === length) {
                child = Object.assign(
                    ...groups.map(value => ({ [value]: val[value] })), 
                    { [valueKey]: 0 }
                );
                acc.push(child);
            } else {
                child = new Map();
            }
            
            accu.set(val[value], child);
            return child;
        }, map)[valueKey] += +val[valueKey];
        
        return acc;
    }, []);
};

// Group by single property
console.log("Grouped by Phase:");
console.log(groupBy(arr, 'Phase', 'Value'));
Grouped by Phase:
[ { Phase: 'Phase 1', Value: 50 }, { Phase: 'Phase 2', Value: 130 } ]

Method 2: Using Object.groupBy() (ES2024)

Modern JavaScript provides Object.groupBy() for simple grouping scenarios:

// Simple grouping by Phase (without aggregation)
const groupedByPhase = Object.groupBy(arr, item => item.Phase);
console.log("Object.groupBy() result:");
console.log(Object.keys(groupedByPhase));

// To aggregate values, we need additional processing
const aggregated = Object.entries(groupedByPhase).map(([phase, items]) => ({
    Phase: phase,
    Value: items.reduce((sum, item) => sum + parseInt(item.Value), 0)
}));

console.log("Aggregated:");
console.log(aggregated);
Object.groupBy() result:
[ 'Phase 1', 'Phase 2' ]
Aggregated:
[ { Phase: 'Phase 1', Value: 50 }, { Phase: 'Phase 2', Value: 130 } ]

Multi-Level Grouping Example

Group by both Phase and Step to create nested groupings:

// Group by multiple properties
console.log("Grouped by Phase and Step:");
const multiGrouped = groupBy(arr, ['Phase', 'Step'], 'Value');
console.log(multiGrouped);
Grouped by Phase and Step:
[
  { Phase: 'Phase 1', Step: 'Step 1', Value: 15 },
  { Phase: 'Phase 1', Step: 'Step 2', Value: 35 },
  { Phase: 'Phase 2', Step: 'Step 1', Value: 55 },
  { Phase: 'Phase 2', Step: 'Step 2', Value: 75 }
]

Performance Comparison

Method Time Complexity Multi-level Support Browser Support
reduce() + Map O(n) Yes All modern browsers
Object.groupBy() O(n) Limited ES2024 (limited)
forEach loops O(n) Manual implementation All browsers

Key Benefits

The Map-based approach offers several advantages:

// Flexible - handles any number of grouping levels
const singleGroup = groupBy(arr, 'Phase', 'Value');
const doubleGroup = groupBy(arr, ['Phase', 'Step'], 'Value');
const tripleGroup = groupBy(arr, ['Phase', 'Step', 'Task'], 'Value');

console.log("Single level groups:", singleGroup.length);
console.log("Double level groups:", doubleGroup.length);
console.log("Triple level groups:", tripleGroup.length);
Single level groups: 2
Double level groups: 4
Triple level groups: 8

Conclusion

The reduce() with Map approach provides the most efficient and flexible solution for grouping arrays of objects. It handles multiple grouping levels and aggregates values in a single pass with O(n) complexity.

Updated on: 2026-03-15T23:19:00+05:30

323 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements