How to group an array by a field
Short answer
Object.groupBy() takes a function that returns the group name and builds an object of arrays:
const products = [
{ title: 'Tea', category: 'drinks' },
{ title: 'Bread', category: 'food' },
{ title: 'Coffee', category: 'drinks' },
];
const groups = Object.groupBy(products, (product) => product.category);
console.log(groups.drinks.map((p) => p.title).join(', '));
console.log(Object.keys(groups).join(', '));Output:
Tea, Coffee
drinks, foodWith reduce
In older environments, build the same object with reduce():
const products = [
{ title: 'Tea', category: 'drinks' },
{ title: 'Bread', category: 'food' },
{ title: 'Coffee', category: 'drinks' },
];
const groups = products.reduce((result, product) => {
(result[product.category] ??= []).push(product.title);
return result;
}, {});
console.log(JSON.stringify(groups));Output:
{"drinks":["Tea","Coffee"],"food":["Bread"]}By a calculated value
The group can be anything the function returns, for example a range of ages:
const ages = [12, 25, 17, 40, 8];
const groups = Object.groupBy(ages, (age) => (age < 18 ? 'children' : 'adults'));
console.log(groups.children.join(', '), '|', groups.adults.join(', '));Output:
12, 17, 8 | 25, 40Common mistake
The result of Object.groupBy() has no prototype, so methods like hasOwnProperty() are missing. Use Object.hasOwn() or the in operator:
const groups = Object.groupBy([1, 2, 3], (n) => (n % 2 ? 'odd' : 'even'));
console.log(typeof groups.hasOwnProperty);
console.log(Object.hasOwn(groups, 'odd'));Output:
undefined
trueFunctions used in this recipe
- Object.groupBy — Groups the elements of an array by a key.
- Array.prototype.reduce — Reduces an array to a single value.
- Map.groupBy — Groups elements into a Map by any key.