@valiv

Как правильно сгруппировать и сделать сортировку массива объектов по определённому ключу?

Как с помощью sort или reduce сгруппировать и сделать сортировку массива объектов по определённому ключу? Т.е есть массив arrObj и нужно по key сгруппировать элементы и отсортировать их по id

const arrObj = [
  {id: 5, key: '555'},
  {id: 7, key: '555'},
  {id: 1, key: '111'},
  {id: 1, key: '222'},
  {id: 2, key: '555'},
  {id: 1, key: '333'},
  {id: 5, key: '111'},
  {id: 3, key: '111'},
]

На выходе должен получиться сгруппированный отсортированный массив объектов, соблюдая порядок их нахождения 1го элемента (т.е '555' идут выше '111' далее '222' и '333'):
const arrObjInput = [
  {id: 2, key: '555'},
  {id: 5, key: '555'},
  {id: 7, key: '555'},
  {id: 1, key: '111'},
  {id: 3, key: '111'},
  {id: 5, key: '111'},
  {id: 1, key: '222'},
  {id: 1, key: '333'},
]
  • Вопрос задан
  • 524 просмотра
Решения вопроса 2
0xD34F
@0xD34F Куратор тега JavaScript
Собираем вспомогательный объект вида { key: первый индекс, где встречается key }:

const keyIndex = arr.reduce((acc, n, i) => (acc[n.key] ??= i, acc), {});

Затем выполняем сортировку по двум параметрам, минимальному индексу и id. Можно отсортировать существующий массив:

arr.sort((a, b) => (keyIndex[a.key] - keyIndex[b.key]) || (a.id - b.id));

Или собрать отсортированный новый:

const sorted = (arr, keys) => arr
  .map(n => [ n ].concat(keys(n)))
  .sort((a, b) => {
    let diff = 0;
    for (let i = 0; ++i < a.length && !(diff = a[i] - b[i]);) ;
    return diff;
  })
  .map(n => n[0]);


const sortedArr = sorted(arr, n => [ keyIndex[n.key], n.id ]);
Ответ написан
sergiks
@sergiks Куратор тега JavaScript
♬♬
Пройти по массиву, складывая встреченные новые ключи в массив уникальных ключей в порядке их встречи.
Индекс ключа в этом массиве и id элемента становятся ключами для сортировки.
Отсортировать (но не взбалтывать!) и удалить добавленный сортировочный ключ.

const dict = [];
arrObj.forEach((el, i) => {
  if (! dict.includes(el.key)) dict.push(el.key);
  el.sorter = dict.indexOf(el.key);
});
arrObj.sort((a, b) => a.sorter < b.sorter ? -1 : (a.sorter > b.sorter ? 1 : a.id - b.id));
arrObj.forEach((el) => delete el.sorter);

console.log(arrObj);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы