Получить свойство 'x' всех объектов внутри свойства 'y' с помощью рекурсии - PullRequest
0 голосов
/ 20 сентября 2011

Рассмотрим следующий пример:

<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>

Есть ли безболезненный способ получить имена всех потомков "Джека МакДаффа I"?

Ответы [ 4 ]

2 голосов
/ 20 сентября 2011

Не используется рекурсия:

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] && используется с оценкой короткого замыкания , гарантирующей, что tree[i] не является нулевым, когда я звоню tree[i].children

tree.push.apply(tree, tree[i].childrens); с использованием применить , что позволяет мне вызывать функцию, в данном случае Array.push , которая принимает любое количество аргументов на tree. Так что эта строка в основном становится tree.push(child0, child1, ... childn);.

, поэтому теперь tree.length увеличено на число детей текущего ребенка.

2 голосов
/ 20 сентября 2011

Самое простое решение - просто использовать базовую рекурсивную функцию:

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 - это функция, которая делает все, что вы хотите сделатькогда вы посещаете узел.

2 голосов
/ 20 сентября 2011

Эта функция вернет всех потомков с заданным именем в генеалогическом древе:

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 уже во множественном числе.

1 голос
/ 20 сентября 2011
for(var names = [], i = 0, l = McDuffFamily.childrens.length; i < l; i++) {
    names.push(McDuffFamily.childrens[i].name);
}

names; // ['Jack McDuff II', 'Poor bastard']

Если вы используете среду (например, Node или MooTools), которая допускает [] .reduce, вы также можете сделать:

names = McDuffFamily.childrens.reduce(function(prev, curr) {
    prev.push(curr.name);
}, []);

names; // ['Jack McDuff II', 'Poor bastard']

Я думаю, что [] .reduce выглядит лучше, ноэто более обременительно

...