@lexstile

Как сгруппировать массив объектов по значениям одного из свойств?

Есть:

const array = [
  { prop: 1 },
  { prop: 2 },
  { prop: 1 },
];

Нужно сгруппировать:

const newArray = [
  [
    { prop: 1 },
    { prop: 1 },
  ],
  [
    { prop: 2 },
  ],
];
  • Вопрос задан
  • 231 просмотр
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
const group = (arr, key) =>
  arr.reduce((acc, n) => {
    const k = n[key];
    (acc[k] = acc[k] || []).push(n);
    return acc;
  }, {});


const result = Object.values(group(array, 'prop'));

UPD. Код немного осовременим (на момент публикации ответа оператор ??= отсутствовал); пусть группировать можно будет не только массивы, а любые итерируемые объекты; также добавим возможность задавать имя группы через функцию (на тот случай, если в качестве имён групп должны будут выступать значения вложенных свойств, или не непосредственно значения свойства, а производные от них - например, есть свойство, представляющее дату, а нужен месяц; или есть имя, а нужна его первая буква и т.п.); ну и ещё в качестве значений групп пусть можно будет брать не исходные значения, а что-то другое:

function group(data, key, val = n => n) {
  const getKey = key instanceof Function ? key : n => n[key];
  const getVal = val instanceof Function ? val : n => n[val];
  const grouped = {};

  for (const n of data) {
    (grouped[getKey(n)] ??= []).push(getVal(n));
  }

  return grouped;
}

Теперь можно делать так:

const groupedBySign = group([ 0, 1, 2, 3, -10, -20, -30, 0 ], Math.sign);

Или так:

const groupedByParity = group(Array(10).keys(), n => [ 'чётные', 'нечётные' ][n & 1]);

Или так:

const chars = group(
  'ABC123?!+',
  n =>
    n.toLowerCase() !== n.toUpperCase() ? 'буква' :
    Number.isInteger(+n)                ? 'цифра' :
                                          'другое'
);

И даже так тоже можно:

<input name="xxx" value="69">
<input name="xxx" value="187">
<input name="xxx" value="666">
<input name="yyy" value="0">

const values = group(document.querySelectorAll('input'), 'name', 'value');

UPD. Наконец-то дождались, и пяти лет ждать не пришлось:

const result = Object.values(Object.groupBy(array, n => n.prop));
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
20 апр. 2024, в 13:56
7000 руб./за проект
20 апр. 2024, в 13:52
7000 руб./за проект
20 апр. 2024, в 13:23
1000 руб./за проект