When processing data, it is very useful to be able to group by variables and calculate statistics for each group. In Javascript, we can use the reduce function to help us build a group by function.
Grouping Objects by Multiple Properties in Array in Javascript
Let’s say we have data such as the following:
var array = [
{thing: 'ball', color: 'red', size: 'big', value: 10},
{thing: 'bat', color: 'blue', size: 'small', value: 15},
{thing: 'bat', color: 'red', size: 'small', value: 11}
{thing: 'bat', color: 'red', size: 'small', value: 21},
{thing: 'bat', color: 'red', size: 'big', value: 13},
{thing: 'helmet', color: 'blue', size: 'medium', value: 30},
{thing: 'helmet', color: 'red', size: 'medium', value: 13},
{thing: 'helmet', color: 'blue', size: 'big', value: 30},
{thing: 'bat', color: 'blue', size: 'medium', value: 14},
{thing: 'ball', color: 'red', size: 'medium', value: 13},
{thing: 'ball', color: 'blue', size: 'small', value: 8}
];
It would be very useful if we could group by the different properties and then sum the values to get the sum of the different groups.
Basically, what we want, is to be able to get the following:
[ { thing: 'ball', value: 31 },
{ thing: 'bat', value: 74 },
{ thing: 'helmet', value: 73 } ]
There are many snippets on how to reduce data and group by one property, but I want to show you how to do it with multiple properties.
The following function gives you the ability to group an array by multiple properties:
function GroupBy(array, keys, variable) {
var i, key, temp, split;
var data = array.reduce((result,currentValue) => {
key = "";
for(i = 0; i < keys.length; i++) {
key = key + currentValue[keys[i]] + "_";
}
if(!result[key]) {
result[key] = 0;
}
result[key] += parseFloat(currentValue[variable]);
return result;
}, {});
var grouped = [];
Object.keys(data).forEach(function(key) {
temp = {};
split = key.split("_");
for(i=0; i < split.length - 1; i++) {
temp[keys[i]] = split[i]
}
temp[variable] = data[key];
grouped.push(temp);
});
return grouped;
}
Below, you can see how running the function with different inputs will give us the desired group sums.
// GroupBy(array,[],"value"):
[ { value: 178 } ]
// GroupBy(array,["thing"],"value")
[ { thing: 'ball', value: 31 },
{ thing: 'bat', value: 74 },
{ thing: 'helmet', value: 73 } ]
// GroupBy(array,["thing","color"],"value"):
[ { thing: 'ball', color: 'red', value: 23 },
{ thing: 'bat', color: 'blue', value: 29 },
{ thing: 'bat', color: 'red', value: 45 },
{ thing: 'helmet', color: 'blue', value: 60 },
{ thing: 'helmet', color: 'red', value: 13 },
{ thing: 'ball', color: 'blue', value: 8 } ]
// GroupBy(array,["thing","color","size"],"value"):
[ { thing: 'ball', color: 'red', size: 'big', value: 10 },
{ thing: 'bat', color: 'blue', size: 'small', value: 15 },
{ thing: 'bat', color: 'red', size: 'small', value: 32 },
{ thing: 'bat', color: 'red', size: 'big', value: 13 },
{ thing: 'helmet', color: 'blue', size: 'medium', value: 30 },
{ thing: 'helmet', color: 'red', size: 'medium', value: 13 },
{ thing: 'helmet', color: 'blue', size: 'big', value: 30 },
{ thing: 'bat', color: 'blue', size: 'medium', value: 14 },
{ thing: 'ball', color: 'red', size: 'medium', value: 13 },
{ thing: 'ball', color: 'blue', size: 'small', value: 8 }]
// GroupBy(array,["size","color","thing"],"value"):
[ { size: 'big', color: 'red', thing: 'ball', value: 10 },
{ size: 'small', color: 'blue', thing: 'bat', value: 15 },
{ size: 'small', color: 'red', thing: 'bat', value: 32 },
{ size: 'big', color: 'red', thing: 'bat', value: 13 },
{ size: 'medium', color: 'blue', thing: 'helmet', value: 30 },
{ size: 'medium', color: 'red', thing: 'helmet', value: 13 },
{ size: 'big', color: 'blue', thing: 'helmet', value: 30 },
{ size: 'medium', color: 'blue', thing: 'bat', value: 14 },
{ size: 'medium', color: 'red', thing: 'ball', value: 13 },
{ size: 'small', color: 'blue', thing: 'ball', value: 8 }]
If you need a different aggregation, you would change the following line:
result[key] += parseFloat(currentValue[variable]);
For example, if you wanted to find the count of each object, you would replace it with:
result[key] += 1;
Finding the minimum and maximum are easy as well, but you have to be careful with how you initialize the property.
Hopefully this article has been useful for you to learn how to aggregate a JavaScript array of objects.