Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check the depth of an object?

I'm working on a permissions system with variable depth; depending on the complexity of a page, there could be more or less levels. I searched StackOverflow to find if this has been asked before, couldn't find it.

If I have this object:

{foo:{bar:{baz : 'baa'}}}

I need it to return 3, it has 3 levels to it.

With this object:

{abc: 'xyz'} 

It would have to be 1.

This is what I have so far:

utils.depthOf = function(object, level){
    // Returns an int of the deepest level of an object
    level = level || 1;

    var key;
    for(key in object){
        if (!object.hasOwnProperty(key)) continue;

        if(typeof object[key] == 'object'){
            level++;
            level = utils.depthOf(object[key], level);
        }
    }

    return level;
}

The problem is it counts sister elements too. It's actually not getting depth, it's counting all members of an object.

like image 286
Kavi Siegel Avatar asked Nov 23 '12 06:11

Kavi Siegel


3 Answers

Well, here you go buddy, a function that does exactly what you need!

utils.depthOf = function(object) {
    var level = 1;
    for(var key in object) {
        if (!object.hasOwnProperty(key)) continue;

        if(typeof object[key] == 'object'){
            var depth = utils.depthOf(object[key]) + 1;
            level = Math.max(depth, level);
        }
    }
    return level;
}

A lot easier than we thought it would be. The issue was how it was incremented, it shouldn't have been recursively adding, rather getting the bottom-most and adding one, then choosing the max between two siblings.

like image 184
Kavi Siegel Avatar answered Nov 01 '22 08:11

Kavi Siegel


This old question was recently resurrected and I don't see any answers as simple as this one (to be fair, this uses techniques not available when the question was written):

const objectDepth = (o) =>
  Object (o) === o ? 1 + Math .max (-1, ... Object .values(o) .map (objectDepth)) : 0

console .log (objectDepth ({foo: {bar: {baz: 'baa'}}}))
console .log (objectDepth ({abc: 'xyz'}))

This, like most answers here, will fail when the input object is cyclic. An answer that addresses that limitation would require much more sophistication.

like image 32
Scott Sauyet Avatar answered Nov 01 '22 09:11

Scott Sauyet


Back from the dead! Throwing my solution into the mix -

function depth (t, mem = new Set)
{ if (mem.has(t))
    return Infinity
  else switch (mem.add(t), t?.constructor)
  { case Object:
    case Array:
      return 1 + Math.max
       ( -1
       , ...Object
           .values(t)
           .map(_ => depth(_, mem))
       )
    default:
      return 0
  }
}

console.log(depth({a: {b: {c: "z"}}}))   // 3
console.log(depth({a: "z"}))             // 1
console.log(depth({}))                   // 0
console.log(depth("z"))                  // 0
console.log(depth({a: [{b: "z"}]}))      // 3

const a = []
a[0] = a
console.log(depth(a))                    // Infinity
like image 22
Mulan Avatar answered Nov 01 '22 07:11

Mulan