Escribí una función recursiva para encontrar un objeto dado y la ruta dentro de ese árbol, pero cuando cambio la identificación del objetivo (aquí: if(tree.targetModuleId === 7)) a 10, recibí un error:
"message": "TypeError no detectado: no se pueden leer las propiedades de undefined (leyendo 'unshift')"
Se supone que debo obtener la ruta: [1,2,5,6,10].
Al final, necesito la opción de que no importa de qué punto quiero obtener una ruta, necesito obtener una respuesta sobre cuál es la ruta y, si no, obtener []
Me encantaría que me ayuden con el tema, les adjunto un código que hice.
let nodes = [ { sourceModuleId: 1, targetModuleId: 2}, { sourceModuleId: 1, targetModuleId: 8}, { sourceModuleId: 2, targetModuleId: 3}, { sourceModuleId: 2, targetModuleId: 5}, { sourceModuleId: 8, targetModuleId: 9}, { sourceModuleId: 3, targetModuleId: 7}, { sourceModuleId: 5, targetModuleId: 6}, { sourceModuleId: 6, targetModuleId: 10}, ]; function toTree(arr) { let arrMap = new Map(arr.map(item => [item.targetModuleId, item])); let tree = []; for (let i = 0; i < arr.length; i++) { let item = arr[i]; if (item.sourceModuleId !==1) { let parentItem = arrMap.get(item.sourceModuleId); if (parentItem) { let { children } = parentItem; if (children) { parentItem.children.push(item); } else { parentItem.children = [item]; } } } else { tree.push(item); } } return tree; } function findInTree(tree) { if (tree.targetModuleId === 7) { let path = [tree.sourceModuleId,tree.targetModuleId]; return {result: tree, path}; } if(tree.children){ for(let i=0; i< tree.children.length;i++){ let tmp = findInTree(tree.children); if (tmp) { tmp.path.unshift(tree.sourceModuleId); return tmp; } } } else { for (let i = 0;i< tree.length; i++) { let tmp = findInTree(tree[i]); if (tmp) { return tmp; } } return []; } } let tree = toTree(nodes); let paths = findInTree(tree); console.log(paths);Algunos problemas en findInTree :
return [] no es correcto: este es un valor verdadero, por lo que el if (tmp) de la persona que llama será verdadero, y no debería ser así. El tipo de datos que devuelve su función debe ser coherente. Parece que debería ser un objeto con propiedades de result y path , pero entonces es inconsistente tener un return [] en su código. Haga que el return null , para indicar que no existe tal objeto y que este valor será falso, dado el comportamiento esperado para la persona que llama. Mueva este return null fuera del bloque else para que también se aplique cuando el bloque if no ejecuta un return .
En el bloque if (tree.children) no es necesario recorrer esos elementos secundarios, ya que eso sucederá en la llamada recursiva. Tenga en cuenta que nunca usa i en ese ciclo, por lo que es una pérdida de tiempo repetir ese cuerpo. Solo quita el lazo.
function findInTree(tree) { if (tree.targetModuleId === 7) { let path = [tree.sourceModuleId, tree.targetModuleId]; return {result: tree, path}; } if (tree.children) { // No need to loop. It will happen in the recursive call let tmp = findInTree(tree.children); if (tmp) { tmp.path.unshift(tree.sourceModuleId); return tmp; } } else { for (let i = 0;i< tree.length; i++) { let tmp = findInTree(tree[i]); if (tmp) { return tmp; } } } return null; // data type consistency }