@Enickckey

Как собрать дерево из массива объектов со свойствами id и parentId?

Есть вот такой массив:

let components = [
  {
    component: "input",
    id: 1,
    parentId: 0,
  },
  {
    component: "select",
    id: 2,
    parentId: 1,
  },
  {
    component: "date",
    id: 3,
    parentId: 2,
  },
  {
    component: "input",
    id: 4,
    parentId: 0,
  },
];

Как сделать так, чтобы на выходе получить вложеные обьекты по логике, что если есть parentId и он совпадает с элементом у которого такой id,то он становится вложенным в него?
То есть, в данном примере это выглядеть должно так:

[
  {
    component: input,
    id: 1,
    parentId: 0,
    components: {
      component: "Select",
      id: 2,
      parentId: 1,
      components: {
        component: "Date",
        id: 3,
        parentId: 2,
      },
    },
  },
  {
    component: "Input",
    id: 4,
    parentId: 0,
  }
];
  • Вопрос задан
  • 147 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
function createTree({
  data,
  idKey = 'id',
  parentKey = 'parentId',
  childrenKey = 'children',
}) {
  const tree = Object.fromEntries(data.map(n => [ n[idKey], { ...n, [childrenKey]: [] } ]));
  return Object.values(tree).filter(n => !tree[n[parentKey]]?.[childrenKey].push(n));
}


const result = createTree({
  data: components,
  childrenKey: 'components',
});
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@GrayHorse
Например.
const map = new Map();
for (const entry of components) {
    const parent = map.get(entry.parentId);
    if (parent) {
        parent.children || (parent.children = []);
        parent.children.push(entry);
    }
    map.set(entry.id, entry);
}
const rootItemId = 1;
console.log(map.get(rootItemId));

С учетом, что с порядком элементов все ок.

Работает в 5-10 раз быстрее, чем решение из соседнего ответа, к слову.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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