试图弄清楚如何以递归方式在此JSON对象中搜索节点。我已经尝试过一些东西,但无法获得:
var tree = {
"id": 1,
"label": "A",
"child": [
{
"id": 2,
"label": "B",
"child": [
{
"id": 5,
"label": "E",
"child": []
},
{
"id": 6,
"label": "F",
"child": []
},
{
"id": 7,
"label": "G",
"child": []
}
]
},
{
"id": 3,
"label": "C",
"child": []
},
{
"id": 4,
"label": "D",
"child": [
{
"id": 8,
"label": "H",
"child": []
},
{
"id": 9,
"label": "I",
"child": []
}
]
}
]
};
我无法使用的解决方案,可能是因为当子节点在数组中时,第一个节点只是一个值:
function scan(id, tree) {
if(tree.id == id) {
return tree.label;
}
if(tree.child == 0) {
return
}
return scan(tree.child);
};
答案 0 :(得分:2)
您的代码只是缺少检查child
数组中节点的每个子节点的循环。此递归函数将返回节点的label
属性;如果树中不存在标签,则返回undefined
:
const search = (tree, target) => {
if (tree.id === target) {
return tree.label;
}
for (const child of tree.child) {
const res = search(child, target);
if (res) {
return res;
}
}
};
var tree = {"id":1,"label":"A","child":[{"id":2,"label":"B","child":[{"id":5,"label":"E","child":[]},{"id":6,"label":"F","child":[]},{"id":7,"label":"G","child":[]}]},{"id":3,"label":"C","child":[]},{"id":4,"label":"D","child":[{"id":8,"label":"H","child":[]},{"id":9,"label":"I","child":[]}]}]};
console.log(search(tree, 1));
console.log(search(tree, 6));
console.log(search(tree, 99));
您还可以使用显式堆栈进行迭代,该堆栈更快,更凉爽并且不会引起堆栈溢出:
const search = (tree, target) => {
const stack = [tree];
while (stack.length) {
const curr = stack.pop();
if (curr.id === target) {
return curr.label;
}
stack.push(...curr.child);
}
};
var tree = {"id":1,"label":"A","child":[{"id":2,"label":"B","child":[{"id":5,"label":"E","child":[]},{"id":6,"label":"F","child":[]},{"id":7,"label":"G","child":[]}]},{"id":3,"label":"C","child":[]},{"id":4,"label":"D","child":[{"id":8,"label":"H","child":[]},{"id":9,"label":"I","child":[]}]}]};
for (let i = 0; ++i < 12; console.log(search(tree, i)));
答案 1 :(得分:0)
scan
可以使用第三个参数以递归方式编写,该参数为要扫描的节点队列建模
const scan = (id, tree = {}, queue = [ tree ]) =>
// if id matches node id, return node label
id === tree.id
? tree.label
// base case: queue is empty
// id was not found, return false
: queue.length === 0
? false
// inductive case: at least one node
// recur on next tree node, append node children to queue
: scan (id, queue[0], queue.slice(1).concat(queue[0].child))
注意JavaScript支持默认参数,scan
的调用站点未更改
console.log
( scan (1, tree) // "A"
, scan (3, tree) // "C"
, scan (9, tree) // "I"
, scan (99, tree) // false
)
验证它是否可以在下面的浏览器中使用
const scan = (id, tree = {}, queue = [ tree ]) =>
id === tree.id
? tree.label
: queue.length === 0
? false
: scan (id, queue[0], queue.slice(1).concat(queue[0].child))
const tree =
{ id: 1
, label: "A"
, child:
[ { id: 2
, label: "B"
, child:
[ { id: 5
, label: "E"
, child: []
}
, { id: 6
, label: "F"
, child: []
}
, { id: 7
, label: "G"
, child: []
}
]
}
, { id: 3
, label: "C"
, child: []
}
, { id: 4
, label: "D"
, child:
[ { id: 8
, label: "H"
, child: []
}
, { id: 9
, label: "I"
, child: []
}
]
}
]
}
console.log
( scan (1, tree) // "A"
, scan (3, tree) // "C"
, scan (9, tree) // "I"
, scan (99, tree) // false
)
答案 2 :(得分:0)
这是使用 object-scan
的解决方案// const objectScan = require('object-scan');
const tree = {"id":1,"label":"A","child":[{"id":2,"label":"B","child":[{"id":5,"label":"E","child":[]},{"id":6,"label":"F","child":[]},{"id":7,"label":"G","child":[]}]},{"id":3,"label":"C","child":[]},{"id":4,"label":"D","child":[{"id":8,"label":"H","child":[]},{"id":9,"label":"I","child":[]}]}]};
const search = (obj, id) => objectScan(['**.id'], {
abort: true,
filterFn: ({ value, parent, context }) => {
if (value === id) {
context.push(parent.label);
return true;
}
return false;
}
})(obj, [])[0];
console.log(search(tree, 1));
// => A
console.log(search(tree, 6));
// => F
console.log(search(tree, 99));
// => undefined
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.7.1"></script>
免责声明:我是object-scan
的作者