Группировка массива объектов по ключу в lodash: примеры

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для того чтобы сгруппировать объекты по определенному ключу в JavaScript, удобно применять метод reduce(), как это показано в эффективном решении ниже:

JS
Скопировать код
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 объект содержит уникальные ключи, которым соответствуют массивы объектов из тех же категорий.

Кинга Идем в IT: пошаговый план для смены профессии

Введение в Reduce

Функция reduce — это мощный инструмент преобразования массива элементов в единый результат, или аккумулятор. Эта функция последовательно применяет заданную функцию к элементам массива, накапливая результат.

В данном случае мы накапливаем объект, где каждое свойство соответствует уникальному ключу в массиве элементов, а значение каждого свойства представляет собой массив объектов с одинаковым ключом.

JS
Скопировать код
const groupBy = (array, key) =>
  array.reduce((accumulator, object) => {
    (accumulator[object[key]] ??= []).push(object);
    return accumulator;
  }, {});

Работа с отсутствующими ключами

В случае наличия объектов без необходимого ключа в массиве, следует отфильтровать их перед применением reduce, чтобы исключить создание свойств с undefined.

JS
Скопировать код
const groupBy = (array, key) => array
  .filter(object => object.hasOwnProperty(key))
  .reduce((accumulator, object) => ((accumulator[object[key]] ??= []).push(object), accumulator), {});

Упрощение благодаря ES6

Современный синтаксис JavaScript (ES6+) позволяет сделать код более лаконичным и понятным. Стрелочные функции, параметры по умолчанию и опциональное связывание значительно упрощают функцию groupBy:

JS
Скопировать код
const groupBy = (array, key) => array.reduce(
  (accumulator, object) => (
    (accumulator[object[key]] = accumulator[object[key]] || []).push(object), accumulator
  ), {}
);

Альтернатива lodash

Если вы предпочитаете работу со сторонними библиотеками, функция _.groupBy() из lodash может оказаться удобным вариантом:

JS
Скопировать код
const _ = require('lodash');
const groupedByType = _.groupBy(pets, 'type');

А функция _.mapValues() может пригодиться при необходимости трансформации значений сгруппированного объекта:

JS
Скопировать код
const transformed = _.mapValues(groupedByType, objs => /* ваш код трансформации здесь */);

Визуализация

Представим банку с разноцветными жвачками:

plaintext
Скопировать код
[🔴, 🔵, 🔴, 🟢, 🔴, 🔵]

Процесс группировки по цвету можно визуализировать следующим образом:

Markdown
Скопировать код
{
  '🔴': [🔴, 🔴, 🔴],
  '🔵': [🔵, 🔵],
  '🟢': [🟢]
}

Здесь каждый ключ соответствует цвету, а значение — массиву жвачек того же цвета.

Углубляемся: Дубликаты, Чистые Объекты и Объединение

Обработка дубликатов

При наличии в данных повторяющихся ключей важно обеспечить уникальность свойств в результирующем объекте. Для отслеживания дубликатов можно использовать возможности ES6, например, Set, или метод .omit из lodash.

Пользуйтесь чистыми объектами

Если вам нужно начать с пустого объекта, его можно создать через Object.create(null). Такой объект не будет иметь наследуемых свойств от Object.prototype.

Объединение сгруппированных объектов

Для объединения сгруппированных объектов можно применять Object.assign. Он позволяет эффективно «склеить» объекты вместе.

Практические примеры и пользовательские вариации

Сортировка групп

Вы можете отсортировать сгруппированные данные по ключам:

JS
Скопировать код
const groupedSorted = Object.keys(groupedByType)
  .sort()
  .reduce((accumulator, key) => ({ ...accumulator, [key]: groupedByType[key] }), {});

// Результатом будет объект с отсортированными ключами

Группировка по нескольким ключам

Метод позволяет группировать данные по нескольким ключам:

JS
Скопировать код
const groupByMultiple = (array, ...keys) => array.reduce((accumulator, object) => {
  keys.reduce((accumulatorInner, key) => ((accumulatorInner[object[key]] ??= []).push(object), accumulatorInner), accumulator);
  return accumulator;
}, {});

Группировка по динамическим свойствам

Возможна группировка по свойствам, определенным динамичной функцией:

JS
Скопировать код
const groupByDynamic = (array, fn) => array.reduce((accumulator, object) => {
  const key = fn(object);
  (accumulator[key] ??= []).push(object);
  return accumulator;
}, {});