考虑以下示例:
<script>
var McDuffFamily = {
name: "Jack McDuff I",
children: [
{
name:"Jack McDuff II",
children: [
{
name:"Jack McDuff III",
children: [
{
name:"Jack McDuff IV"
},
{
name:"Jonh McDuff I",
children: [
{
name:"Jonh McDuff I",
children: []
}
]
}
]
},
{
name:"Shena McDuff"
}
]
},
{
name:"Poor bastard",
children: [
{
name:"Citzen I",
children: [
{
name:"Darth Vader"
}
]
},
{
name:"Citzen II",
children: []
}
]
}
]
};
</script>
有没有任何无痛的方法来检索所有“Jack McDuff I”后代的名字?
答案 0 :(得分:2)
最简单的解决方案是使用基本的递归函数:
function traverse(parent, visit) {
var ii;
visit(parent.name);
for (ii = 0; ii < parent.children.length; ii += 1) {
traverse(parent.children[ii], visit);
}
}
parent
的初始值为McDuffFamily
,visit
是一个函数,可以在您访问节点时执行任何操作。
答案 1 :(得分:2)
此函数将返回家族树中给定名称的所有后代:
function getDescendants(family, name)
{
var result = [];
var iterate = function(node, isDescendant)
{
if(isDescendant)
result.push(node.name);
else
isDescendant = (node.name == name);
for(var i=0; i<node.children.length; i++)
iterate(node.children[i], isDescendant);
};
iterate(family, false);
return result;
}
它将返回一个包含所有后代名称的数组。
PS:我写了children
而不是childrens
,因为children
已经是复数。
答案 2 :(得分:2)
不使用递归:
var tree =[McDuffFamily];
var kids = [];
for (i=0; i < tree.length; i++) {
tree[i] && tree.push.apply(tree, tree[i].childrens)
kids.push(tree[i]);
}
kids; // all children
奇怪部分的细分:
tree[i] && tree.push.apply(tree, tree[i].childrens);
tree[i] &&
与short-circuit evaluation一起使用,确保在我致电tree[i]
tree[i].children
不为空
tree.push.apply(tree, tree[i].childrens);
使用apply允许我调用一个函数,在本例中为Array.push,它在tree
上接受任意数量的参数。因此该行基本上变为tree.push(child0, child1, ... childn);
。
所以现在tree.length
已经增加了当前孩子的孩子数量。
答案 3 :(得分:1)
for(var names = [], i = 0, l = McDuffFamily.childrens.length; i < l; i++) {
names.push(McDuffFamily.childrens[i].name);
}
names; // ['Jack McDuff II', 'Poor bastard']
如果您正在使用允许[] .reduce的环境(如Node或使用MooTools),您也可以这样做:
names = McDuffFamily.childrens.reduce(function(prev, curr) {
prev.push(curr.name);
}, []);
names; // ['Jack McDuff II', 'Poor bastard']
我认为[] .reduce看起来更好,但它更加沉重