fabsta
fabsta

Reputation: 145

How to prune/delete nodes in nested/tree-like JSON?

I have the following JSON example to represent a tree.

[
    {
        "label": "node1",
        "children": [
            {
                "label": "Human"
            },
            {
                "label": "Chimpanzee"
            }
        ]
    },
    {
        "label": "node2",
        "children": [
            {
                "label": "node3",
                "children": [
                    {
                        "label": "Rat"
                    },
                    {
                        "label": "Mouse"
                    }
                ]
            },
            {
                "label": "BigRat"
            }
        ]
    }
]

What I would like to do now, is the following: Given a list of labels (e.g. BigRat, Mouse), how can I delete the corresponding nodes in the JSON?

I just can't get my head around this.

Any help is much appreciated!

Thanks

Upvotes: 1

Views: 7534

Answers (1)

Ray Waldin
Ray Waldin

Reputation: 3227

Since your tree is essentially an object array, where each object has a label and an optional child array, what you need to prune are array elements, either in the main tree array or in one of it's branches.

You definitely do not want to use delete to delete array elements, since that leaves you with a sparse array. Instead, you should splice out array elements.

You should, on the other hand, use delete to remove object properties, like children once they're empty. Here's the code I would use:

function prune(array, label) {
    for (var i = 0; i < array.length; ++i) {
        var obj = array[i];
        if (obj.label === label) {
            // splice out 1 element starting at position i
            array.splice(i, 1);
            return true;
        }
        if (obj.children) {
            if (prune(obj.children, label)) {
                if (obj.children.length === 0) {
                    // delete children property when empty
                    delete obj.children;

                    // or, to delete this parent altogether
                    // as a result of it having no more children
                    // do this instead
                    array.splice(i, 1);
                }
                return true;
            }
        }
    }
}

Now assuming your tree was called tree and the label you wanted pruned was node3, you would call prune like so:

var wasItPruned = prune(tree, "node3");

Upvotes: 9

Related Questions