This fork of JamieMason's implementation changes the key
parameter to be an array of keys instead of just a single key. This makes it possible to group by multiple properties instead of just one.
const groupBy = keys => array =>
array.reduce((objectsByKeyValue, obj) => {
const value = keys.map(key => obj[key]).join('-');
objectsByKeyValue[value] = (objectsByKeyValue[value] || []).concat(obj);
return objectsByKeyValue;
}, {});
Click to see TypeScript version
/**
* Group array of objects by given keys
* @param keys keys to be grouped by
* @param array objects to be grouped
* @returns an object with objects in `array` grouped by `keys`
* @see <https://gist.github.com/mikaello/06a76bca33e5d79cdd80c162d7774e9c>
*/
const groupBy = <T>(keys: (keyof T)[]) => (array: T[]): Record<string, T[]> =>
array.reduce((objectsByKeyValue, obj) => {
const value = keys.map((key) => obj[key]).join('-');
objectsByKeyValue[value] = (objectsByKeyValue[value] || []).concat(obj);
return objectsByKeyValue;
}, {} as Record<string, T[]>);
const cars = [
{ brand: 'Audi', produced: '2016', color: 'black' },
{ brand: 'Audi', produced: '2017', color: 'white' },
{ brand: 'Ford', produced: '2016', color: 'red' },
{ brand: 'Ford', produced: '2016', color: 'white' },
{ brand: 'Peugot', produced: '2018', color: 'white' }
];
const groupByBrand = groupBy(['brand']);
const groupByColor = groupBy(['color']);
const groupByBrandAndYear = groupBy(['brand', 'produced']);
console.log(
JSON.stringify({
carsByBrand: groupByBrand(cars),
carsByColor: groupByColor(cars),
carsByBrandAndYear: groupByBrandAndYear(cars)
}, null, 2)
);
{
"carsByBrand": {
"Audi": [
{
"brand": "Audi",
"produced": "2016",
"color": "black"
},
{
"brand": "Audi",
"produced": "2017",
"color": "white"
}
],
"Ford": [
{
"brand": "Ford",
"produced": "2016",
"color": "red"
},
{
"brand": "Ford",
"produced": "2016",
"color": "white"
}
],
"Peugot": [
{
"brand": "Peugot",
"produced": "2018",
"color": "white"
}
]
},
"carsByColor": {
"black": [
{
"brand": "Audi",
"produced": "2016",
"color": "black"
}
],
"white": [
{
"brand": "Audi",
"produced": "2017",
"color": "white"
},
{
"brand": "Ford",
"produced": "2016",
"color": "white"
},
{
"brand": "Peugot",
"produced": "2018",
"color": "white"
}
],
"red": [
{
"brand": "Ford",
"produced": "2016",
"color": "red"
}
]
},
"carsByBrandAndYear": {
"Audi-2016": [
{
"brand": "Audi",
"produced": "2016",
"color": "black"
}
],
"Audi-2017": [
{
"brand": "Audi",
"produced": "2017",
"color": "white"
}
],
"Ford-2016": [
{
"brand": "Ford",
"produced": "2016",
"color": "red"
},
{
"brand": "Ford",
"produced": "2016",
"color": "white"
}
],
"Peugot-2018": [
{
"brand": "Peugot",
"produced": "2018",
"color": "white"
}
]
}
}
See playcode.io for example.
@shravanivish
This does not look related to the group by function in this gist, please write unrelated questions in other places that are more appropriate, e.g. Stackoverflow.
BTW, your problem could be fixed by using another reduce, or by modifying your existing. But please follow this another place.