Grouping an Array and Counting items creating new array based on Groups in JavaScript

When working with arrays of objects in JavaScript, you often need to group data by specific properties and count unique items. This article demonstrates how to group an array by region and count unique users per region.

Problem Statement

Suppose we have an array of objects representing user data across different regions:

const arr = [
    { region: "Africa", fruit: "Orange", user: "Gary" },
    { region: "Africa", fruit: "Apple", user: "Steve" },
    { region: "Europe", fruit: "Orange", user: "John" },
    { region: "Europe", fruit: "Apple", user: "bob" },
    { region: "Asia", fruit: "Orange", user: "Ian" },
    { region: "Asia", fruit: "Apple", user: "Angelo" },
    { region: "Africa", fruit: "Orange", user: "Gary" }
];

console.log("Original array:", arr);
Original array: [
  { region: 'Africa', fruit: 'Orange', user: 'Gary' },
  { region: 'Africa', fruit: 'Apple', user: 'Steve' },
  { region: 'Europe', fruit: 'Orange', user: 'John' },
  { region: 'Europe', fruit: 'Apple', user: 'bob' },
  { region: 'Asia', fruit: 'Orange', user: 'Ian' },
  { region: 'Asia', fruit: 'Apple', user: 'Angelo' },
  { region: 'Africa', fruit: 'Orange', user: 'Gary' }
]

We need to create a new array that groups the data by region and counts unique users for each region. Notice that "Gary" appears twice in Africa, so he should only be counted once.

Expected Output

The desired output should look like this:

[
    {
        "region": "Africa",
        "count": 2
    },
    {
        "region": "Europe", 
        "count": 2
    },
    {
        "region": "Asia",
        "count": 2
    }
]

Using forEach with Object Context

Here's an elegant solution using forEach with a custom context object to track both regions and unique users:

const arr = [
    { region: "Africa", fruit: "Orange", user: "Gary" },
    { region: "Africa", fruit: "Apple", user: "Steve" },
    { region: "Europe", fruit: "Orange", user: "John" },
    { region: "Europe", fruit: "Apple", user: "bob" },
    { region: "Asia", fruit: "Orange", user: "Ian" },
    { region: "Asia", fruit: "Apple", user: "Angelo" },
    { region: "Africa", fruit: "Orange", user: "Gary" }
];

const groupByArea = (arr = []) => {
    const res = [];
    arr.forEach(function(el) {
        let key = [el.region, el.user].join('|');
        if (!this[el.region]) {
            this[el.region] = { region: el.region, count: 0 };
            res.push(this[el.region]);
        }
        if (!this[key]) {
            this[key] = true;
            this[el.region].count++;
        }
    }, Object.create(null));
    return res;
}

console.log(groupByArea(arr));
[
    { region: 'Africa', count: 2 },
    { region: 'Europe', count: 2 },
    { region: 'Asia', count: 2 }
]

Alternative Approach Using Map

Here's another approach using a Map for cleaner tracking:

const groupByRegionMap = (arr = []) => {
    const regionMap = new Map();
    const userSet = new Set();
    
    arr.forEach(item => {
        const userKey = `${item.region}|${item.user}`;
        
        if (!regionMap.has(item.region)) {
            regionMap.set(item.region, { region: item.region, count: 0 });
        }
        
        if (!userSet.has(userKey)) {
            userSet.add(userKey);
            regionMap.get(item.region).count++;
        }
    });
    
    return Array.from(regionMap.values());
}

console.log(groupByRegionMap(arr));
[
    { region: 'Africa', count: 2 },
    { region: 'Europe', count: 2 },
    { region: 'Asia', count: 2 }
]

How It Works

The solution works by:

  1. Creating unique keys: Combining region and user with a delimiter (e.g., "Africa|Gary")
  2. Tracking regions: Adding new region objects to the result array when first encountered
  3. Preventing duplicates: Only incrementing count when a unique region-user combination is found
  4. Using context object: The forEach second parameter provides a shared context for tracking

Comparison of Approaches

Method Readability Performance Modern JS
forEach with context Moderate Good ES5+
Map and Set High Excellent ES6+

Conclusion

Both approaches effectively group array data and count unique users per region. The Map/Set approach offers better readability and leverages modern JavaScript features, while the forEach method demonstrates creative use of function context.

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

411 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements