Группировка и суммирование значений в массиве объектов
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Для группировки объектов по определённому свойству великолепно подходит метод Array.prototype.reduce()
— это наилучший выбор:
const groupBy = (arr, prop) => arr.reduce((acc, item) => {
(acc[item[prop]] = acc[item[prop]] || []).push(item);
return acc;
}, {});
// Проиллюстрируем применение этой функции на примере.
const result = groupBy([{id: 1, val: 'A'}, {id: 1, val: 'B'}, {id: 2, val: 'C'}], 'id');
На выходе мы получаем удобную для поиска структуру, где ключами являются значения свойства id
, а значениями – массивы соответствующих объектов.
Ускорение работы с помощью цикла 'for'
Если вы работаете с большим объёмом данных и производительность для вас имеет значение, выбирайте цикл for
:
const groupByForLoop = (arr, prop) => {
const grouped = {};
for (let i = 0; i < arr.length; i++) {
let key = arr[i][prop];
if (!grouped[key]) grouped[key] = [];
grouped[key].push(arr[i]);
}
return grouped;
};
Цикл for
помогает избежать ненужных затрат на вызовы функций и достигнуть высокой скорости исполнения.
Добавляем гибкость с помощью ES6 Map
Когда важен порядок элементов и требуется гибкость, вам может пригодиться структура данных Map
из ES6:
const groupByMap = (arr, prop) => {
return arr.reduce((acc, item) => {
const key = item[prop];
const collection = acc.get(key) || [];
acc.set(key, [...collection, item]);
return acc;
}, new Map());
};
Использование Map
обеспечивает сохранение порядка элементов, что может быть критичным для некоторых задач.
Группировка в сочетании с суммированием
Если вам требуется осуществить группировку и одновременно суммировать значения, это можно выполнить за один проход:
const groupBySum = (arr, groupProp, sumProp) => {
return arr.reduce((acc, item) => {
let key = item[groupProp];
let val = item[sumProp];
acc[key] = (acc[key] || 0) + val;
return acc;
}, {});
};
Такой подход позволяет включить операцию суммирования непосредственно в процесс группировки, снижая общее количество проходов по массиву.
TypeScript: Долгой живи типовая безопасность
Для тех, кому ближе TypeScript, добавление типовой безопасности к функциям группировки будет неоценимым:
function groupBy<T, K extends keyof T>(arr: T[], prop: K): Record<T[K], T[]> {
return arr.reduce((acc: Record<T[K], T[]>, item: T) => {
const groupKey = item[prop];
if (!acc[groupKey]) acc[groupKey] = [];
acc[groupKey].push(item);
return acc;
}, {} as Record<T[K], T[]>);
}
// Пример применения типов в TypeScript:
const result = groupBy([{id: 1, value: 'A'}, {id: 1, value: 'B'}, {id: 2, value: 'C'}], 'id');
В TypeScript
применение строгой типизации повышает безопасность кода и предотвращает возникновение ошибок типизации.
Визуализация
Продемонстрируем процесс группировки на наглядном примере:
Представьте себе сад 🌳, полный разнообразных фруктов.
Каждому виду фруктов соответствует своя корзина:
Яблоки: 🍎🍎🍎 → [Корзина🧺]
Бананы: 🍌🍌 → [Корзина🧺]
Вишня: 🍒🍒🍒🍒 → [Корзина🧺]
Вот как работает функция groupby
:
const fruitBasket = groupBy(fruits, fruit => fruit.type);
// В итоге, у нас получаются корзины, аккуратно наполненные 🍎, 🍌 и 🍒!
Функция Groupby
позволяет эффективно организовывать объекты по общим характеристикам.
Решение задачи: больше примеров использования
Гибкость критериев группировки
Предположим, вам нужно адаптировать критерии группировки. Это можно сделать без особых сложностей:
const groupByFunction = (arr, fn) => arr.reduce((acc, item) => {
const key = fn(item);
(acc[key] = acc[key] || []).push(item);
return acc;
}, {});
// Пример использования: группировка гораздо шире, чем просто сортировка по свойству...
const groupedByCustomLogic = groupByFunction(objects, (obj) => obj.date.getFullYear());
Этот вариант groupBy
позволяет применять любую функцию для расчета ключей группировки.
Погружение во вложенные свойства
Если вложенные свойства вызывают у вас беспокойство, прорывайтесь в их глубины следующим образом:
const groupByDeep = (arr, propPath) => {
return arr.reduce((acc, item) => {
const keys = propPath.split('.');
const key = keys.reduce((o, k) => (o || {})[k], item);
(acc[key] = acc[key] || []).push(item);
return acc;
}, {});
};
Таким образом, можно осуществлять группировку элементов, учитывая свойства на разных уровнях вложенности.
Полезные материалы
- Документация по методу
reduce()
на MDN — подробно изучите тонкости методаreduce()
. - Обсуждение методов группировки объектов на основе массива на Stack Overflow — здесь представлено множество примеров группировки.
- Документация Lodash — ознакомьтесь с функцией
groupBy()
в Lodash для более сложных операций. - Документация по методу
map()
на MDN — овлейте все возможности методаmap()
. - Документация по методу
filter()
на MDN — изучите детали применения методаfilter()
. - Документация по методу
sort()
на MDN — глубокое погружение в тело сортировки массивов.