【问题标题】:Retrieve property 'x' of all objects inside property 'y' with recursion使用递归检索属性“y”内所有对象的属性“x”
【发布时间】:2011-09-20 18:39:42
【问题描述】:

考虑以下示例:

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

【问题讨论】:

    标签: javascript algorithm oop recursion hierarchy


    【解决方案1】:

    不使用递归:

    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] &amp;&amp;short-circuit evaluation 一起使用,确保在我调用tree[i].childrentree[i] 不为空

    tree.push.apply(tree, tree[i].childrens); 使用apply 允许我调用一个函数,在本例中为Array.push,它在tree 上接受任意数量的参数。所以那行基本上变成了tree.push(child0, child1, ... childn);

    所以现在tree.length 增加了当前子节点的子节点数。

    【讨论】:

    • 看起来很有趣,但老实说,我不太明白它是如何工作的
    • 哪一部分?如果你愿意,我可以解释一下
    • tree[i] && tree.push.apply(tree, tree[i].childrens)
    • jsperf.com/push-apply-vs-recursion 有点慢,但是这个短路评估和 push.apply 的东西值得回答
    【解决方案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 是一个函数,当你访问一个节点时,它可以做任何你想做的事情。

    【讨论】:

    • 这里最快的'n'clean 解决方案。谢谢。
    【解决方案3】:

    此函数将返回给定名称的所有后代家族树:

    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已经是复数形式了。

    【讨论】:

      【解决方案4】:
      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 看起来更好,但它更费力

      【讨论】:

      • 我相信他想要整个家谱,而不仅仅是杰克麦克达夫的孩子。 IE 孩子的孩子。
      • 啊,那我的例子不完全在那里,嗯
      猜你喜欢
      • 2021-01-01
      • 2020-11-18
      • 2021-12-10
      • 2011-05-12
      • 1970-01-01
      • 2014-03-16
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      相关资源
      最近更新 更多