Группировка массива объектов по ключу в lodash: примеры
Быстрый ответ
Для того чтобы сгруппировать объекты по определенному ключу в JavaScript, удобно применять метод reduce(), как это показано в эффективном решении ниже:
const groupBy = (array, key) =>
array.reduce((accumulator, object) => {
(accumulator[object[key]] ??= []).push(object);
return accumulator;
}, {});
const pets = [
{type: 'dog', name: 'Max'},
{type: 'cat', name: 'Kitty'},
{type: 'dog', name: 'Rex'}
];
const groupedByType = groupBy(pets, 'type');
console.log(groupedByType); // вывод: {dog: [{...}, {...}], cat: [{...}]}
Возвращаемый функцией groupBy объект содержит уникальные ключи, которым соответствуют массивы объектов из тех же категорий.

Введение в Reduce
Функция reduce — это мощный инструмент преобразования массива элементов в единый результат, или аккумулятор. Эта функция последовательно применяет заданную функцию к элементам массива, накапливая результат.
В данном случае мы накапливаем объект, где каждое свойство соответствует уникальному ключу в массиве элементов, а значение каждого свойства представляет собой массив объектов с одинаковым ключом.
const groupBy = (array, key) =>
array.reduce((accumulator, object) => {
(accumulator[object[key]] ??= []).push(object);
return accumulator;
}, {});
Работа с отсутствующими ключами
В случае наличия объектов без необходимого ключа в массиве, следует отфильтровать их перед применением reduce, чтобы исключить создание свойств с undefined.
const groupBy = (array, key) => array
.filter(object => object.hasOwnProperty(key))
.reduce((accumulator, object) => ((accumulator[object[key]] ??= []).push(object), accumulator), {});
Упрощение благодаря ES6
Современный синтаксис JavaScript (ES6+) позволяет сделать код более лаконичным и понятным. Стрелочные функции, параметры по умолчанию и опциональное связывание значительно упрощают функцию groupBy:
const groupBy = (array, key) => array.reduce(
(accumulator, object) => (
(accumulator[object[key]] = accumulator[object[key]] || []).push(object), accumulator
), {}
);
Альтернатива lodash
Если вы предпочитаете работу со сторонними библиотеками, функция _.groupBy() из lodash может оказаться удобным вариантом:
const _ = require('lodash');
const groupedByType = _.groupBy(pets, 'type');
А функция _.mapValues() может пригодиться при необходимости трансформации значений сгруппированного объекта:
const transformed = _.mapValues(groupedByType, objs => /* ваш код трансформации здесь */);
Визуализация
Представим банку с разноцветными жвачками:
[🔴, 🔵, 🔴, 🟢, 🔴, 🔵]
Процесс группировки по цвету можно визуализировать следующим образом:
{
'🔴': [🔴, 🔴, 🔴],
'🔵': [🔵, 🔵],
'🟢': [🟢]
}
Здесь каждый ключ соответствует цвету, а значение — массиву жвачек того же цвета.
Углубляемся: Дубликаты, Чистые Объекты и Объединение
Обработка дубликатов
При наличии в данных повторяющихся ключей важно обеспечить уникальность свойств в результирующем объекте. Для отслеживания дубликатов можно использовать возможности ES6, например, Set, или метод .omit из lodash.
Пользуйтесь чистыми объектами
Если вам нужно начать с пустого объекта, его можно создать через Object.create(null). Такой объект не будет иметь наследуемых свойств от Object.prototype.
Объединение сгруппированных объектов
Для объединения сгруппированных объектов можно применять Object.assign. Он позволяет эффективно «склеить» объекты вместе.
Практические примеры и пользовательские вариации
Сортировка групп
Вы можете отсортировать сгруппированные данные по ключам:
const groupedSorted = Object.keys(groupedByType)
.sort()
.reduce((accumulator, key) => ({ ...accumulator, [key]: groupedByType[key] }), {});
// Результатом будет объект с отсортированными ключами
Группировка по нескольким ключам
Метод позволяет группировать данные по нескольким ключам:
const groupByMultiple = (array, ...keys) => array.reduce((accumulator, object) => {
keys.reduce((accumulatorInner, key) => ((accumulatorInner[object[key]] ??= []).push(object), accumulatorInner), accumulator);
return accumulator;
}, {});
Группировка по динамическим свойствам
Возможна группировка по свойствам, определенным динамичной функцией:
const groupByDynamic = (array, fn) => array.reduce((accumulator, object) => {
const key = fn(object);
(accumulator[key] ??= []).push(object);
return accumulator;
}, {});


