Reputation: 775
I have a tree:
type Tree = {
id: string;
pathToNode?: string[];
children: Tree[];
};
export const treeData: Tree = {
id: '1',
children: [
{
id: '2',
children: [
{ id: '3', children: [] },
{ id: '4', children: [] },
],
},
{ id: '5', children: [] },
],
};
And I wish to find the path to the id and return that path (or in other words, the parent nodes to that node).
This is what I have (but it's not working):
const findPath = (tree: Tree, id: string, pathStack: string[]) => {
if (tree.id === id) {
tree.pathToNode = pathStack;
return { id: tree.id, path: tree.pathToNode };
}
pathStack.push(tree.id);
if (tree.children.length) {
tree.children.map((node) => findPath(node, id, pathStack));
}
return { id: tree.id, path: pathStack };
};
If I call findPath and pass in id: '2', I should get:
const pathStack:string[] = [];
const result = findPath(treeData, '2', pathStack);
// result should equal: {id: '2', pathToNode: ['1']}
If I call findPath and pass in id: '4', I should get:
const pathStack:string[] = [];
const result = findPath(treeData, '4', pathStack);
// result should equal: {id: '4', pathToNode: ['1', '2']}
If I call findPath and pass in id: '5', I should get:
const pathStack:string[] = [];
const result = findPath(treeData, '5', pathStack);
// result should equal: {id: '5', pathToNode: ['1']}
And if I pass in the root id of '1', the response would be {'1', pathToNode: []}
Upvotes: 0
Views: 986
Reputation: 2237
Your logic looks fine, only need a few corrections I have added some comments in you code where you need correction
const findPath = (tree: Tree, id: string, pathStack: string[]) => {
if (tree.id === id) {
tree.pathToNode = pathStack; // no need to add pathstack to tree
return { id: tree.id, path: tree.pathToNode }; // use pathStack instead of tree.pathToNode
}
pathStack.push(tree.id);
if (tree.children.length) {
tree.children.map((node) => findPath(node, id, pathStack)); // this will loops to all your childs even if you find the result node
//So use for loop and break the loop when you find the result node
}
return { id: tree.id, path: pathStack };
};
my code is
const findPath = (tree: Tree, id: string, pathStack: string[]) => {
if (tree.id === id)
return { id: tree.id, path: pathStack };
pathStack.push(tree.id);
for (const node of tree.children) {
const result = findPath(node, id, [...pathStack]);
if (result) return result; //this will stop going deeper or to unwanted childs after getting the result
}
};
As discussed in the comment to find paths of certain nodes in an array.
let foundPaths = [];
let path
arr.map(element => {
path = findPath(tree, element.id);
if(path) {foundPaths.push(path)}
})
Upvotes: 1
Reputation: 386868
You need to return early for the children and respect the return value.
const
treeData = { id: '1', children: [{ id: '2', children: [{ id: '3', children: [] }, { id: '4', children: [] }] }, { id: '5', children: [] }] },
findPath = (tree, id, pathStack = []) => {
if (tree.id === id) return { id: tree.id, path: pathStack };
pathStack.push(tree.id);
for (const node of tree.children) {
const result = findPath(node, id, [...pathStack]);
if (result) return result;
}
};
console.log(findPath(treeData, '4'));
console.log(findPath(treeData, '5'));
Upvotes: 1