Creé una función que genera una ruta del nodo de destino desde la raíz del árbol. Pero hay un pequeño error en el que estoy atascado.
Implementación:
interface FSNode { name: string; id: string; type: 'file' | 'dir'; isPlaceholder?: boolean; showIcons: boolean; ext?: string; children?: FSNode[]; } const getFSNodePath = (tree: Array<FSNode>, targetNode: FSNode) => { let currentPath = ''; function buildPath(subTree: Array<FSNode>, targetNode: FSNode): string | undefined{ for(const node of subTree){ // loop all and find if the node matches the target if(node.id === targetNode.id){ // add the targetn node to path end currentPath = currentPath + '/' + node.name; return currentPath; } else if(node.children){ // if it doesn't match, check if it has children // if children present, check the node in them ( recursion ) // before checking the children, add the node name to path ( to build the path name ) currentPath = currentPath + '/' + node.name; const path = buildPath(node.children, targetNode); // only return(stop) the fn when there is any path ( coming from above case node.id === targetNode.id ); // if there is no path, means it couldn't find any thing, don't return ( stop ) because need to check the children // of other nodes as well and if we return the loop will also stop. if(path) return path; } } } const path = buildPath(tree, targetNode); return path; };Insecto:
si quiero una ruta para index.html, el código primero se ejecuta a través de los dos primeros nodos raíz. Primero verifica la carpeta src y luego sus hijos. Si no encuentra el nodo de destino en sus hijos, el código comprueba el segundo nodo raíz y, finalmente, el tercero y devuelve la ruta. Pero devuelve una ruta incorrecta como esta: /src/index.html en lugar de /index.html .
La posible solución a esto sería restablecer la variable currentPath a cadenas vacías después de que salgamos de las carpetas anidadas. Pero no puedo averiguar dónde debo restablecer la variable currentPath.
La pista de @Naren funcionó. Al pasar la ruta a la función buildPath, restablece la ruta cuando la función regresa.
const getFSNodePath = (tree: Array<FSNode>, targetNode: FSNode) => { function buildPath(subTree: Array<FSNode>, targetNode: FSNode, currentPath: string): string | undefined{ for(const node of subTree){ // loop all and find if the node matches the target if(node.id === targetNode.id){ // add the targetn node to path end return currentPath + '/' + node.name; } else if(node.children){ // if it doesn't match, check if it has children // if children present, check the node in them ( recursion ) // before checking the children, add the node name to path ( to build the path name ) const path = buildPath(node.children, targetNode, currentPath + '/' + node.name); // only return(stop) the fn when there is any path ( coming from above case node.id === targetNode.id ); // if there is no path, means it couldn't find any thing, don't return ( stop ) because need to check the children // of other nodes as well and if we return the loop will also stop. if(path) return path; } } } const path = buildPath(tree, targetNode, ''); return path; };Cada llamada de su función buildPath está modificando el mismo currentPath , por lo que "/src" se adjunta cuando ingresa al primer subárbol y no se elimina al salir.
Para evitar esto, convierta la ruta en un argumento de buildPath :
const getFSNodePath = (root: FSNode, targetNode: FSNode): string => { /** * returns the path as an array of tree nodes, from `root` to `targetNode` * or `null` if no child under the `path` matches the targetNode */ const buildPath = (currentPath: FsNode[], targetNode: FSNode): FSNode[] | null => { const currentNode = currentPath[currentPath.length - 1]; if (currentNode.id === targetNode.id) return currentPath; for (const child of currentNode.children ?? []) { const pathFound = buildPath(currentPath.concat(child), targetNode); if (pathFound) return pathFound; } return null; } const path = findPath([rootNode], targetNode) ?? [] return path.reduce((joined, node) => `${joined}/${node.name}`, '') }