使用递归检索属性“y”内的所有对象的属性“x”

时间:2011-09-20 18:39:43

标签: javascript algorithm oop recursion hierarchy

考虑以下示例:

<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”后代的名字?

4 个答案:

答案 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的初始值为McDuffFamilyvisit是一个函数,可以在您访问节点时执行任何操作。

答案 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看起来更好,但它更加沉重