#javascript #typescript
Вопрос:
Я создал функцию, которая генерирует путь к целевому узлу из корня дерева. Но есть небольшая ошибка, на которой я застрял.
Реализация:
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;
};
Жук:
- Src
- app.js
- Компоненты
- index.html
если я хочу найти путь для index.html, код сначала проходит через первые два корневых узла. Сначала он проверяет папку src, а затем ее дочерние элементы. Если он не находит целевой узел в своих дочерних узлах, код проверяет второй корневой узел и, в конечном счете, третий и возвращает путь. Но он возвращает неправильный путь примерно так — /src/index.html
вместо /index.html
этого .
Возможным решением этой проблемы было бы сбросить currentPath
переменную в пустые строки после того, как мы выйдем из вложенных папок. Но я не могу понять, где я должен сбросить переменную currentPath.
Комментарии:
1. передайте
currentPath
как параметр и попробуйте.buildPath(tree, targetNode, currentPath)
2. Мне жаль, но я не понимаю, что произойдет при прохождении текущего пути.
Ответ №1:
Каждый вызов вашей buildPath
функции изменяет одно и то же currentPath
, поэтому "/src"
прикрепляется при входе в первое поддерево и не удаляется при выходе из него.
Чтобы избежать этого, сделайте путь аргументом 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}`, '')
}
Ответ №2:
Подсказка @Naren сработала. Передавая путь функции buildPath, она сбрасывает путь при возврате функции.
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;
};