Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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:
- Creating unique keys: Combining region and user with a delimiter (e.g., "Africa|Gary")
- Tracking regions: Adding new region objects to the result array when first encountered
- Preventing duplicates: Only incrementing count when a unique region-user combination is found
-
Using context object: The
forEachsecond 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.
