Fawzan
Fawzan

Reputation: 4849

Recursively accumulate a path to an array from a Javascript Object

I am trying to find all the child elements of a node in the following Javascript Object.

var graphObj = {

        a : {
            'true' : ['e', 'i'],
            'false' : ['u'],
            'blah' : 'extra key'
        },
        e : {
            'true' : ['o'],
            'false' : ['v'],
            'blah' : 'extra key'
        },
        f : {
            'true' : [],
            'false' : [],
            'blah' : 'extra key'
        },
        i : {
            'true' : [],
            'false' : ['f'],
            'blah' : 'extra key'
        },
        o : {
            'true' : [],
            'false' : [],
            'blah' : 'extra key'
        },
        u: {
            'true': [],
            'false': [],
            'blah' : 'extra key'
        },
        v: {
            'true': [],
            'false': [],
            'blah' : 'extra key'
        },
        z: {
            'true': [],
            'false': [],
            'blah' : 'extra key'
        },

    };

This method will return the children of a given node

var getChilds = function (opId) {


            var r;

            if (graphObj.hasOwnProperty(opId)) {

                var t = graphObj[opId].true.slice();
                var f = graphObj[opId].false.slice();

                r = t.concat(f);


            } else {
                console.log('No node found with the ID');
            }

            return r;

        }

        console.log(getChilds('a'));

current [output] => ['e', 'i', 'u']

But I need a way to accumulate all the child nodes by recursively traversing the graph.

required output => ['e', 'i', 'u', 'o', 'v', 'f']

Can anyone help me?

Note : This is a directed graph. No loops. Also true and false are the only keys on the node storing edge types.

Upvotes: 0

Views: 466

Answers (1)

Andrew Templeton
Andrew Templeton

Reputation: 1696

I took your "order does not matter" comment into consideration and also made sure to only include ['true', 'false'] as edge type keys to traverse on.

var graphObj = {

        a : {
            'true' : ['e', 'i'],
            'false' : ['u']
        },
        e : {
            'true' : ['o'],
            'false' : ['v']
        },
        f : {
            'true' : [],
            'false' : []
        },
        i : {
            'true' : [],
            'false' : ['f']
        },
        o : {
            'true' : [],
            'false' : []
        },
        u: {
            'true': [],
            'false': []
        },
        v: {
            'true': [],
            'false': []
        }
    };
console.log(getChildren('a')); // [ 'e', 'o', 'v', 'i', 'f', 'u' ]


function getChildren(entry) {
    var visited = {};
    var children = {};
    traverse(entry);
    return Object.keys(children);
    function traverse (entry) {
        if (visited[entry]) {
            return;
        }
        if (!graphObj[entry]) {
            throw new Error('Node "' + entry + '" does not exist in graph!');
        }
        var edgeTypes = ['true', 'false'];
        // USE THIS LINE FOR ARBITRARY EDGE TYPES
        // var edgeTypes = Object.keys(graphObj[entry]);
        visited[entry] = true;
        edgeTypes.forEach(function(edgeType) {
            var nodeList = graphObj[entry][edgeType] || [];
            nodeList.forEach(function(nodeLetter) {
                children[nodeLetter] = true;
                traverse(nodeLetter);
            });
        });
    }
}

Upvotes: 1

Related Questions