[英]Recursively find arbitrary node path in tree
我有一棵由以下结构组成的对象树:
interface Node {
name: string;
children?: Node[];
}
例如, { name: "foo", children: [ { name: "bar" } ] }
是有效树。 我正在尝试获取任意节点的地址,该地址可以是叶子,作为到达它的路径的数组返回,该节点将通过对象引用进行比较。 给定示例,我具有以下结构:
var data = {
name: "Languages",
children: [{
name: "Functional",
children: [
{ name: "OCaml" },
{ name: "Haskell" },
{ name: "Erlang" }
]
}, {
name: "Imperative",
children: [
{ name: "BASIC" },
{ name: "Clipper" }
]
}]
};
期望,例如,如果我有一个存储在名为ocaml
的变量中的OCaml
引用,该变量恰好指向内存中的该引用,则将返回步骤数组以及到达该引用的路径,在这种情况下, [0, 0]
。
我已经可以找到对象,但是我不能存储先前的索引,因为这是不确定的:
var tree = function(struct, cmp) {
if (struct.children) {
var lookup = [];
for (var i = 0; i < struct.children.length; i++) {
lookup.push(tree(struct.children[i], cmp));
}
return lookup;
} else {
if (struct === cmp) {
return "PASS";
}
return "FAIL";
}
}
我可以找到该元素,但是如何存储以前的索引以从基数中获取它呢?
尝试跟踪局部作用域变量中的路径将不起作用,因为每个递归调用都会创建一个新作用域。 假设您想要的东西与您已经拥有的东西非常相似,则相当小的更改是使索引的查找路径成为该方法的返回值。 递归调用的基本情况(当没有子节点时)返回[]
(找到)或null
(找不到)。
var tree = function(struct, cmp) {
if (struct === cmp) {
// `cmp` is found at current `struct`.
return [];
} else if (struct.children) {
for (var i = 0; i < struct.children.length; i++) {
var path = tree(struct.children[i], cmp);
if (path !== null) {
// `cmp` is found at `path` in `struct.children[i]`,
// so prefix `i` to `path` to get the path in `struct`.
path.unshift(i);
return path;
}
}
}
// `cmp` not found in this branch of the tree.
return null;
};
console.log(tree(data, data.children[0].children[0])); // outputs [0, 0]
console.log(tree(data, data.children[0].children[2])); // outputs [0, 2]
console.log(tree(data, data.children[1].children[1])); // outputs [1, 1]
我将data
包装在一个数组中。 对于所有节点,您可以将引用存储在一个对象中,例如
var lookUp = {
'OCaml':getNode(data, 'OCaml'),
'BASIC': getNode(data, 'BASIC')
};
或者,您可以通过遍历对象来构建参考。
var data = [{ name: "Languages", children: [{ name: "Functional", children: [ { name: "OCaml" }, { name: "Haskell" }, { name: "Erlang" } ] }, { name: "Imperative", children: [ { name: "BASIC" }, { name: "Clipper" } ] }] }]; function getNode(array, name) { function findNode(a, i, o) { if (a.name === name) { node = o[i] return true; } return Array.isArray(a.children) && a.children.some(findNode); } var node; array.some(findNode); return node; } var lookUp = { 'OCaml':getNode(data, 'OCaml'), 'BASIC': getNode(data, 'BASIC') }; lookUp.BASIC.name = 'Basic'; document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.