0

I have an object structure like so;

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

All values in children have the same structure as above except that their parent would be would a reference to the object that has it as its child.

How can I easily iterate over all children of children etc but in the child's object context?

I know how I can loop the children for one object

obj.children.forEach(function(child) {

});

But how can I iterate all children of children, when the children could be into 10-20-30 deep heirachy?

1
  • You must use a recursive function. Commented May 19, 2013 at 5:20

3 Answers 3

5

Use recursion.

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

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

The way this works becomes evident if we state it in plain English:

  • If there are no children, just call the callback with the node. (base case)
  • If there are children, first deal with ourself, and then do this whole procedure for each child.

This type of recursion is called preorder traversal.

Sign up to request clarification or add additional context in comments.

1 Comment

Could you please explain what is happening here please?
1

We will write a recursive function. Recursive means that it will execute itself again:

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]);
        }
    }
}

Now if we have an object like this:

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: []
        }
    ]
};

We can iterate all over it:

iterate(obj);

FIDDLE DEMO (open your console in browser)

Comments

1

The standard way is to use recurson like icktoofay is suggesting.

Something that is a little more annoying in this kind of processing is how to manage traversal in "chunks" (e.g. if you want to do this in "background" in a javascript program using a timer).

In this case you can use an explicit stack:

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);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.