Печать всех узлов, начиная с определенного корня

#javascript

#javascript

Вопрос:

У меня есть следующая структура данных:

 const arr = [
 {
  "id": 58,
  "parent_id": null
 },
 {
   "id": 59,
   "parent_id": 58
 },
 {
  "id": 60,
  "parent_id": 59
 },
 {
  "id": 61,
  "parent_id": 58
 },
 {
  "id": 62,
  "parent_id": 61
 },
 {
  "id": 63,
  "parent_id": 62
 },
 {
  "id": 64,
  "parent_id": 63
 }
]
  

который представляет следующее дерево:

введите описание изображения здесь

Я хочу распечатать все узлы из определенного корня. Как я могу это сделать?

Например:

  • При выборе root 58, он должен печатать все элементы с 58 по 64.
  • При выборе root 61 он должен печатать элементы 61 — 64.

Я пытался использовать рекурсию и цикл for, но, похоже, это пересекает только 1 ветвь дерева.

 const printNodes = (currItems, allItems) => {
  for (const currItem of currItems) {
    const items = arr.filter(item => item.parent_id === currItem.id)

    allItems = allItems.concat(items)

    return printNodes(items, allItems)
  }

  return allItems
}

console.log(printNodes([arr[0]], []))
  

Комментарии:

1. Вам нужно объяснить больше. По какому шаблону должен проходить путь?

2. @MajedBadawi Он должен проходить по всем путям, ведущим от выбранного корня, порядок посещения не имеет значения.

Ответ №1:

Передайте весь массив и передайте начальный узел вашей функции. Затем выполните поиск по всем дочерним элементам и рекурсивно вызовите функцию снова, по одному разу для каждого дочернего элемента.

 const collectNodes = (arr, startNode, results)=>{
    results.push(startNode);
    const childs = arr.filter(item=>item.parent_id === startNode.id);
    if (childs.length) {
        childs.forEach(c => collectNodes(arr, c, results));
    }
    return results;
}

console.log(collectNodes(arr, arr[3], []))

// Prints
// {id: 61, parent_id: 58}
// {id: 62, parent_id: 61}
// {id: 63, parent_id: 62}
// {id: 64, parent_id: 63}
  

По соображениям производительности я бы создал свойство child с массивом перед итерацией.

Ответ №2:

Вы могли бы взять объект со всеми отношениями и отобразить id .

 const
    getNodes = parent => [parent, ...(relations[parent] || []).flatMap(getNodes)],
    data = [{ id: 58, parent_id: null }, { id: 59, parent_id: 58 }, { id: 60, parent_id: 59 }, { id: 61, parent_id: 58 }, { id: 62, parent_id: 61 }, { id: 63, parent_id: 62 }, { id: 64, parent_id: 63 }],
    relations = data.reduce((r, { id, parent_id }) => {
        if (!r[parent_id]) r[parent_id] = [];
        r[parent_id].push(id);
        return r;
    }, {});

console.log(getNodes(58));
console.log(getNodes(61));  
 .as-console-wrapper { max-height: 100% !important; top: 0; }