Tengo una matriz plana donde cada nodo tiene una identificación y una matriz de las identificaciones de sus hijos:
[ {id: 1, children: [2, 3]}, {id: 2, children: []}, {id: 3, children: [4]}, {id: 4, children: []}, {id: 5, children: []}, ]¿Cómo puedo, preferiblemente en Javascript, crear una jerarquía con los objetos reales como niños anidados en lugar de solo sus ID?
[ {id: 1, children: [ {id: 2, children: []}, {id: 3, children: [ {id: 4, children: []} ]} ]}, {id: 5, children: []}, ]He intentado lo siguiente pero solo funciona la primera capa:
function getHierarchyFromFlatArray(nodes) { const nodeById = new Map(nodes.map(el => [el.id, el])) for (const node of nodes) { node.children = node.children.map(id => { let val = nodeById.get(id) let idx = nodes.findIndex(item => item.id=== id) nodes.splice(idx, 1) return val }) } return nodes }Aquí hay una manera de resolver el problema. Primero cree un Map que haga referencia a los valores de id al valor del node . Luego procese cada uno de los nodos (reemplazando la lista de hijos con un árbol recursivamente, al mismo tiempo eliminando esos nodos del Mapa) en la lista si su valor de id está presente en el Mapa.
const nodes = [ {id: 1, children: [2, 3]}, {id: 2, children: []}, {id: 3, children: [4]}, {id: 4, children: []}, {id: 5, children: []}, ] const nodemap = new Map(nodes.map(n => [n.id, n])); const tree = (node) => { nodemap.delete(node.id); return node.children.length ? { id : node.id, children : node.children.map(c => tree(nodemap.get(c))) } : node } result = [] nodes.forEach(node => { if (nodemap.has(node.id)) result.push(tree(node)) }) console.log(result)Pasos:
undefined para los nodos raíz).undefined en nuestro mapeo. const getHierarchyFromFlatArray = (nodes) => { const nodeById = {} const parent = {} nodes.forEach((node) => { nodeById[node.id] = node node.children.forEach((child) => { parent[child] = node.id }) node.children = [] }) nodes.forEach((node) => { const parentId = parent[node.id] // ? If current node is the child of some other node if (parentId && nodeById[parentId]) { nodeById[parentId].children.push(node) } }) return nodes.filter((node) => parent[node.id] === undefined) } const input = [ {id: 1, children: [2, 3]}, {id: 2, children: []}, {id: 3, children: [4]}, {id: 4, children: []}, {id: 5, children: []}, ] const output = getHierarchyFromFlatArray(input) console.log(output) /* output = [ {id: 1, children: [ {id: 2, children: []}, {id: 3, children: [ {id: 4, children: []} ]} ]}, {id: 5, children: []}, ] */