wmash
wmash

Reputation: 4202

Recursion in hierarchical tree

I am tying to iterate through a hierarchical tree in javascript to determine how many levels it has. Here is a short snippet of my tree:

parent: [
   { id: 1 }
   {
       child1: [
           { id: 2 }
           {
               child2: [
                   { id: 3 }
                   {}
               ]
           }
       ],
       child3: [
           { id: 4 }
           { 
               child4: [
                   { id: 5 }
                   {}
               ],
               child5: [
                   { id: 6 }
                   {
                       child6: [
                           { id: 7 }
                           {}
                       ]
                   }
               ]
           }
       ]
   }
]

There will be an unknown number of parents and children. There is 1 certainty:

My goal is to determine the number of levels that the tree has. For example, there are 4 levels in this example tree (parent = 1, child1 + child3 are on the same level (2), child4 and child5 are on the same level (3) and child6 = 4).

This is my code so far:

for (var j in dependencyTree) {
    if (getObjectSize(dependencyTree[j][1]) > 0) {
        levelsArray.push(j + ': ' + recursiveFunction(dependencyTree[j][1], 1));
    }
}


function recursiveFunction(obj, lvls) {
    if (getObjectSize(obj) > 0) {
        for (var i in obj) {
            recursiveFunction(obj[i][1], lvls++);
        }
    }
    return lvls;
}

getObjectSize() just returns the size of the object. I.e. how many direct children it has. For example, object parent will return 2 (child1 and child3).

In the beginning, the top level parent children are passed into the function.

I think my problem is that for loop (for (var i in obj)) because that may grab the first child parent has (child1) and will eventually return the number of levels that child1 has even though child3 has more.

Any help appreciated.

(Have not yet attempted lodash but have been told it offers no recursive help)

EDIT

{
    "Mobile": [
        {
            "id": 89
        },
        { 
            "Mobile Client": [
                {
                    "id": 100 
                },
                {}
            ]
        }
    ],
    "Service Platform": [
        {
            "id": 90
        },
        {
            "Service Platform": [
                {..."

EDIT (new proposed format):

I have talked with my colleague, the new proposed data format is:

[
    {
        "name": "Mobile",
        "id": 89,
        "children": [
            {
                "name": "Mobile Client",
                "id": 100,
                "children": {}
            }
        ]
    }
];

This seems like much more workable data and will be implemented tomorrow

Upvotes: 0

Views: 2126

Answers (2)

Daniel
Daniel

Reputation: 35674

here is some sample code to give you an idea how to traverse the data - the information is visible through console.

var a = [
   { id: 1 },
   {
   child1: [
       { id: 2 },
       {
           child2: [
               { id: 3 },
               {}
           ]
       }
   ],
   child3: [
       { id: 4 },
       { 
           child4: [
               { id: 5 },
               {}
           ],
           child5: [
               { id: 6 },
               {
                   child6: [
                       { id: 7 },
                       {}
                   ]
               }
           ]
       }
   ]
   }
];

var getNumChildren=function(obj){
  var a = 0;
  if(obj[1]){
for (var key in obj[1]) {
  a++;
  var res = getNumChildren(obj[1][key]);
  console.log(res,a);
  a += res;
}
  }
  return a;
}


console.log(getNumChildren(a));

as far as formatting the data goes, this format might make more sense and be easier to understand and use

[
  {"id":1,
    "children":[
      {"id":2,"children":[
        {"id":4,"children":[]},
        {"id":5,"children":[]}
      ]},
      {"id":3,"children":[]}
    ]
  }
]

edit

if you update the data format, you can use this code.

var data =[
  {"id":1,
    "children":[
      {"id":2,"children":[
        {"id":4,"children":[]},
        {"id":5,"children":[]}
      ]},
      {"id":3,"children":[]}
    ]
  },
  {"id":6,"children":[]}
]

var getNumChildren=function(ca){
  var n = ca.length;
  ca.map(function(c){n += getNumChildren(c.children);})
  return n
}

document.write("result: " + getNumChildren(data));

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386520

Despite the format, this solution iterates over all elements in arrays as well as in objecs and count them.

function count(array) {
    var c = 0;
    array.forEach(function (a) {
        c++;
        if (typeof a === 'object') {
            Object.keys(a).forEach(function (k) {
                if (Array.isArray(a[k])) {
                    c += count(a[k]);
                }
            });
        }
    });
    return c;
}

var parent = [{ id: 1 }, { child1: [{ id: 2 }, { child2: [{ id: 3 }, {}, ] }], child3: [{ id: 4 }, { child4: [{ id: 5 }, {}], child5: [{ id: 6 }, { child6: [{ id: 7 }, {}] }] }] }],
    newFormat = [{ "name": "Mobile", "id": 89, "children": [{ "name": "Mobile Client", "id": 100, "children": {} }] }];

document.write('<pre>' + JSON.stringify(count(parent), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(parent, 0, 4) + '</pre><hr>');
document.write('<pre>' + JSON.stringify(count(newFormat), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(newFormat, 0, 4) + '</pre>');

Upvotes: 1

Related Questions