Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як згрупувати масив за ознакою: Object.groupBy і Map.groupBy?

Групування масиву за ознакою довго писали вручну через reduce. З ES2024 для цього є вбудовані функції.

Object.groupBy(items, callback) - результат у звичайному об'єкті, ключі - те, що повернув колбек:

const orders = [
  { id: 1, status: 'paid', total: 100 },
  { id: 2, status: 'new', total: 50 },
  { id: 3, status: 'paid', total: 70 },
];

const byStatus = Object.groupBy(orders, (order) => order.status);
// { paid: [{ id: 1, ... }, { id: 3, ... }], new: [{ id: 2, ... }] }

const bySize = Object.groupBy(orders, ({ total }) => (total >= 70 ? 'large' : 'small'));

Map.groupBy(items, callback) - результат у Map. Потрібен, коли ключ - не рядок: об'єкт, дата, число, яке не має перетворюватися на рядок:

const byCustomer = Map.groupBy(orders, (order) => customersById.get(order.customerId));
byCustomer.get(someCustomer);   // замовлення конкретного об'єкта-клієнта

Особливості:

  • це статичні функції, а не методи масиву: Object.groupBy(arr, fn), а не arr.groupBy(fn). Метод масиву планували, але він конфліктував зі старими бібліотеками, що розширювали Array.prototype;
  • об'єкт від Object.groupBy має прототип null: у нього немає hasOwnProperty, toString тощо. result.hasOwnProperty('paid') кине помилку - перевіряйте через Object.hasOwn(result, 'paid') чи 'paid' in result;
  • групи відсутніх значень просто не створюються - порожніх масивів для «ненайдених» статусів не буде;
  • елементи в групах ідуть у порядку вихідного масиву.

Як це робили раніше (і досі доводиться в старих оточеннях):

const byStatus = orders.reduce((groups, order) => {
  (groups[order.status] ??= []).push(order);
  return groups;
}, {});

Порівняння з Laravel: це аналог collect($orders)->groupBy('status'). Агрегати по групах далі рахують звичайними методами: Object.entries(byStatus).map(([status, list]) => [status, list.length]).

Підтримка: усі сучасні браузери з 2024 року і Node.js 21+. Для старших середовищ - поліфіл (core-js) чи reduce.

Докладніше в документації: Object.groupBy()

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання