Search code examples
javascriptarraysnode.jstrie

Constructing a hierarchy tree in javascript


I am trying to build a hierarchy tree for Category and Sub-category and so on from the facets that I am getting from the SOLR. The input is of the form:

['445',
79,
'398',
73,
'710',
32,
'398|760',
28,
'398|760|779',
28,
'445|446',
10]

where data in single quotes represents the categories and number after that represents frequency.

Given the above array, the output I need should be in the format:

[
    {
        "id": 445,
        "count": 79,
        "children": [
            {
                "id": 446,
                "count": 10
            }
        ]
    },
    {
        "id": 398,
        "count": 73,
        "children": [
            {
                "id": 760,
                "count": 28,
                "children": [
                    {
                        "id": 779,
                        "count": 28
                    }
                ]
            }
        ]
    },
    {
        "id": 710,
        "count": 32
    }
]

I am trying to build tree out of the same- for an efficient solution, but not able to do the same. Would someone know how to get it working- or any other time efficient solution for the same.

Thanks!


Solution

  • This should do what you want with the exception that nodes with no children will still have a node.children property so you can see how many children any node in the tree has by using node.children.length

    var o=["445", 79, "398", 73, "710", 32, "398|760", 28, "398|760|779", 28, "445|446", 26, "710|1045", 25, "445|452", 24, "381", 19, "445|943", 19, "398|730", 18, "398|730|607", 18, "367", 16, "445|446|451", 15, "351", 14, "351|363", 14, "351|363|365", 14, "381|395", 14, "381|395|566", 14, "445|526", 14, "445|526|769", 14, "367|372", 12, "710|1045|1119", 11, "398|410", 10, "398|483", 9, "445|452|743", 8, "367|372|377", 7, "398|483|757", 7, "445|446|792", 7, "445|452|744", 7, "445|452|719", 6, "398|410|411", 5];
    
    var nodeMap={};
    var nodeLevels=[];
    for(var i=0;i<o.length;i+=2)
    {
        var catLineage=o[i].split('|');
        var cat=catLineage[catLineage.length-1];
        var depth=catLineage.length;
        while(depth>nodeLevels.length){nodeLevels.push([]);}
        nodeMap[cat]={id:cat,count:o[i+1],depth:depth,parents:catLineage.slice(0,catLineage.length-1)};
        nodeLevels[depth-1].push(cat);
    }
    var tree=[];
    var treeNodeLookup={};
    for(var i=0;i<nodeLevels.length;i++)
    {
        for(var j=0;j<nodeLevels[i].length;j++)
        {
            var nodeId=nodeLevels[i][j];
            var nodeDepth=nodeMap[nodeId].depth;
            var nodeCount=nodeMap[nodeId].count;
            var parents=nodeMap[nodeId].parents;
            var pointer={children:tree};
            if(parents.length>0){pointer=treeNodeLookup[parents[0]];}
            var node={id:nodeId,count:nodeCount,children:[]};
            pointer.children.push(node);
            treeNodeLookup[nodeId]=pointer.children[pointer.children.length-1];
        }
    }
    console.log(tree);
    

    Using console.log(JSON.stringify(tree)); my output is:

    [{"id":"445","count":79,"children":[{"id":"446","count":26,"children":[]},{"id":"452","count":24,"children":[]},{"id":"943","count":19,"children":[]},{"id":"526","count":14,"children":[]},{"id":"451","count":15,"children":[]},{"id":"769","count":14,"children":[]},{"id":"743","count":8,"children":[]},{"id":"792","count":7,"children":[]},{"id":"744","count":7,"children":[]},{"id":"719","count":6,"children":[]}]},{"id":"398","count":73,"children":[{"id":"760","count":28,"children":[]},{"id":"730","count":18,"children":[]},{"id":"410","count":10,"children":[]},{"id":"483","count":9,"children":[]},{"id":"779","count":28,"children":[]},{"id":"607","count":18,"children":[]},{"id":"757","count":7,"children":[]},{"id":"411","count":5,"children":[]}]},{"id":"710","count":32,"children":[{"id":"1045","count":25,"children":[]},{"id":"1119","count":11,"children":[]}]},{"id":"381","count":19,"children":[{"id":"395","count":14,"children":[]},{"id":"566","count":14,"children":[]}]},{"id":"367","count":16,"children":[{"id":"372","count":12,"children":[]},{"id":"377","count":7,"children":[]}]},{"id":"351","count":14,"children":[{"id":"363","count":14,"children":[]},{"id":"365","count":14,"children":[]}]}]