Как сгруппировать массив по полю
Короткий ответ
Object.groupBy() принимает функцию, которая возвращает имя группы, и строит объект из массивов:
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(', '));Результат:
Tea, Coffee
drinks, foodЧерез reduce
В старых средах соберите такой же объект через 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));Результат:
{"drinks":["Tea","Coffee"],"food":["Bread"]}По вычисленному значению
Группой может быть что угодно, что вернёт функция, например диапазон возрастов:
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(', '));Результат:
12, 17, 8 | 25, 40Частая ошибка
У результата Object.groupBy() нет прототипа, поэтому методов вроде hasOwnProperty() у него нет. Используйте Object.hasOwn() или оператор in:
const groups = Object.groupBy([1, 2, 3], (n) => (n % 2 ? 'odd' : 'even'));
console.log(typeof groups.hasOwnProperty);
console.log(Object.hasOwn(groups, 'odd'));Результат:
undefined
trueФункции из этого ответа
- Object.groupBy — Группирует элементы массива по ключу.
- Array.prototype.reduce — Сводит массив к одному значению.
- Map.groupBy — Группирует элементы в Map по любому ключу.