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

Есть массив с объектами:

[
  {
    id: 0,
    relatedItemID: 3
  },
  {
    id: 1
  },
  {
    id: 2
  },
  {
    id: 3
    relatedItemID: 1
  },
]

У некоторых элементов есть привязка по id к другому элементу. Нужно получить массив cо сгруппированными и отсортированными внутри групп элементами согласно их связям:

[
  [
    {
      id: 0,
      relatedItemID: 3
    },
    {
      id: 3
      relatedItemID: 1
    },
    {id: 1}
  ],
  [{id: 2}], // на этот элемент никто не ссылается

]

Группы это по сути хронологическая цепь связей. id0 ссылается на id3, по этому id3 в группе идет после id0. id3 ссылается на id1 - по этому в группе id1 идет после id3 [id0 -> id3 -> id1]. id1 - ни на кого не ссылается, по этому он становится последним звеном в этой группе связей. На id2 никто не ссылается, по этому он один в отдельной группе.


Ответы (1 шт):

Автор решения: vsemozhebuty

Если я правильно понимаю задачу и если можно изменять исходный массив, можно попробовать так:

const items1 = [
  {
    id: 0,
    relatedItemID: 3,
  },
  {
    id: 1,
  },
  {
    id: 2,
  },
  {
    id: 3,
    relatedItemID: 1,
  },
];

const items2 = [];

while (items1.length > 0) {
  let item = items1.shift();

  if (items1.some(({ relatedItemID }) => relatedItemID === item.id)) {
    items1.push(item);
    continue;
  }

  const group = [];
  group.push(item);
  while (item.relatedItemID !== undefined) {
    const relatedId = items1.findIndex(({ id }) => id === item.relatedItemID);
    const [related] = items1.splice(relatedId, 1);
    group.push(related);
    item = related;
  }
  items2.push(group);
}

console.log(items2);

→ Ссылка