Группировка массива объектов по ключу в 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;
}, {});