Как сгруппировать id объектов, у которых совпадают остальные свойства?

Есть массив:

const arr = [
  { id: 1, we: 'cn', le: null },
  { id: 2, we: 'cn', le: null },
  { id: 3, we: 'cn', le: 'car' },
  { id: 1, we: 'cn', le: null },
];

Как сравнивать объекты? id у объектов разные, а значение других ключей могут совпадать, ключей одинаковое количество.
По результатам сравнения объектов надо создать массив объектов вида [{id: 1, match: [2]}],
где свойство id - это id первого объекта из совпавших, а match содержит id остальных совпавших объектов.
Если id уже есть в match в любом объекте, то с ним объект не создавать, например {id: 2, match:[1]} излишен.
  • Вопрос задан
  • 242 просмотра
Решения вопроса 1
sergiks
@sergiks Куратор тега JavaScript
♬♬
Нет смысла выделять первый id как особый, и добавлять к нему в массив match другие похожие — все id с одинаковыми прочими значениями равноправны. Поэтому предлагаю как результат просто массивы, где собраны id с совпадающими свойствами.

Понадобится хэш из ключей, исключая id, упорядоченных по алфавиту, и значений. Этот отпечаток будет одинаков у совпадающих объектов, несмотря на разные id (и разный порядок ключей).

Получаем объекты { id, hash }, затем составляем «словарь», где ключи – хэши, а значения – Set'ы с id, у которых оказался одинаковый хэш. Set'ы – чтобы не повторялись одинаковые id.

Потом остаётся из этих Set'ов сделать обычные массивы.
const arr = [
  { id: 1, we: 'cn', le: null },
  { id: 2, le: null, we: 'cn' },
  { id: 3, we: 'cn', le: 'car' },
  { id: 1, we: 'cn', le: null },
];

const dict = arr
  .map(({ id, ...obj }) => {
    const keys = Object.keys(obj).sort();
    const ordered = keys.reduce((acc, c) => {
      acc[c] = obj[c];
      return acc;
    }, {});
    return { id, hash: JSON.stringify(ordered) };
  })
  .reduce((acc, c) => {
    (acc[c.hash] ??= new Set()).add(c.id);
    return acc;
  }, {});

Object.values(dict).map(s => [...s]); // [ [1, 2], [3] ]
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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