0

私はそのようなオブジェクト構造を持っています。

{
   this.parent = undefined;
   this.children = [];
}

のすべての値は、それを子として持つオブジェクトへの参照になることchildrenを除いて、上記と同じ構造を持っています。parent

子などのすべての子を簡単に反復できますが、子のオブジェクトコンテキストではどうすればよいですか?

1 つのオブジェクトの子をループする方法を知っています

obj.children.forEach(function(child) {

});

しかし、子供たちが10-20-30の深い階層になる可能性がある場合、どうすれば子供たちのすべての子供たちを繰り返すことができますか?

4

3 に答える 3

5

再帰を使用します。

function deepForEach(node, fn) {
    fn(node);
    node.children.forEach(function(child) {
        deepForEach(child, fn);
    });
}

deepForEach(obj, function(obj) {
    console.log(obj);
});

これがどのように機能するかは、平易な英語で述べると明らかになります。

  • 子がいない場合は、ノードでコールバックを呼び出すだけです。(規範事例)
  • 子供がいる場合は、まず自分自身に対処してから、この手順全体を子供ごとに実行します。

このタイプの再帰は、preorder traversalと呼ばれます。

于 2013-05-19T05:20:04.580 に答える
1

再帰関数を書きます。再帰的とは、それ自体を再度実行することを意味します。

function iterate(obj) {
    // we will write the parent and the name
    console.log(obj.parent + ' | ' + obj.name);

    // if it has children
    if (obj.children.length) {
        // for each child
        for (var i = 0, l = obj.children.length; i < l; i++) {
            // we will call this function again
            arguments.callee(obj.children[i]);
        }
    }
}

次のようなオブジェクトがあるとします。

var obj = {
    name: 'P1',
    parent: undefined,
    children: [
        {
            name: 'P2',
            parent: 'P1',
            children: []
        },
        {
            name: 'P3',
            parent: 'P1',
            children: [
                {
                    name: 'P4',
                    parent: 'P3',
                    children: [
                        {
                            name: 'P5',
                            parent: 'P4',
                            children: []
                        }
                    ]
                }
            ]
        },
        {
            name: 'P6',
            parent: 'P1',
            children: []
        }
    ]
};

全体を反復できます。

iterate(obj);

FIDDLE DEMO(ブラウザでコンソールを開きます)

于 2013-05-19T05:32:18.283 に答える
1

標準的な方法は、icktoofay が提案しているように再帰を使用することです。

この種の処理で少し煩わしいのは、「チャンク」でトラバーサルを管理する方法です (たとえば、タイマーを使用する JavaScript プログラムの「バックグラウンド」でこれを実行する場合)。

この場合、明示的なスタックを使用できます。

function process_tree(root_node,
                      process_node,
                      chunk_size,
                      completion_call)
{
    var todo = []; // nodes that need processing

    function processOneChunk() {
        for (var j=0; todo.length && j<chunk_size; j++) {
            var x = todo.pop();
            process_node(x);
            for (var i=0; i<x.children.length; i++) {
                todo.push(x.children[i]);
            }
        }
        if (todo.length) {
            setTimeout(processOneChunk, 0);
        } else {
            completion_call();
        }
    }

    todo.push(root_node);
    setTimeout(processOneChunk, 0);
}
于 2013-05-19T06:44:39.083 に答える