I'm working with a tree nodes and I want to create a function to find an item by its ID.
What is the best and optimal solution to get it?
I think it will be a recursive function, but I'm not sure and I want a help please to choose what I will use to resolve this issue :)
This is my example:
const treeData = [
{
title: 'parent 1',
key: 11,
children: [
{
title: 'parent 1-0',
key: 12,
children: [
{
title: 'leaf',
key: 13,
children: [
{
title: 'leaf111',
key: 14,
},
{
title: 'leaf',
key: 15,
},
],
},
{
title: 'leaf666',
key:88,
},
],
},
{
title: 'parent 1-1',
key: 55,
children: [
{
title: (
<span
style={{
color: '#1890ff',
}}
>
sss
</span>
),
key: '0-0-1-0',
},
],
},
],
},
];
Input : 14
Output : {title: 'leaf111',key: 14},
CodePudding user response:
We can create a rerusive function that:
- Loops though each object in the array and
- Returns the object if id matches
- Calls itself with the objects children
const treeData = [{title: 'parent 1', key: 11, children: [{title: 'parent 1-0', key: 12, children: [{title: 'leaf', key: 13, children: [{title: 'leaf111', key: 14, }, {title: 'leaf', key: 15, }, ], }, {title: 'leaf666', key:88, }, ], }, {title: 'parent 1-1', key: 55, children: [{title: '(<span style={{color: \'#1890ff\', }} > sss </span> )', key: '0-0-1-0', }, ], }, ], }, ];
const findById = (e, id) => {
for (let o of e) {
return (o.key == id) ? o : findById(o.children, id);
}
}
const res = findById(treeData, 14);
console.log(res);
Output:
{
"title": "leaf111",
"key": 14
}
CodePudding user response:
You can use a tree walker, which traverses the tree and calls a provided function upon visiting each node. The provided function could check to see if the node matches the provided ID.
An example:
function getNodeById(id) {
let matchingNode;
walk(tree, node => {
if(node.key === 14) {
matchingNode = node;
}
});
return matchingNode;
}
A tree walker can be implemented using recursion, as you mention. In a preorder operation, which starts at the topmost node, the walker takes the tree (the root node) and on each invocation:
- calls the callback function with the current node
- for each child node, calls itself with the child node and callback
function walker(node, cb) {
cb(node);
if (Array.isArray(node.children)) {
node.children.forEach(child => walker(child, cb));
}
}
For use with React, you can implement your own walking using React.Children.forEach, or you may prefer try a library like https://github.com/FormidableLabs/react-ssr-prepass.