22

我正在研究具有可变深度的权限系统;根据页面的复杂性,可能会有更多或更少的级别。我搜索了 StackOverflow 以查找之前是否有人问过这个问题,但找不到。

如果我有这个对象:

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

我需要它返回 3,它有 3 个级别。

有了这个对象:

{abc: 'xyz'} 

它必须是1。

这是我到目前为止所拥有的:

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;
}

问题是它也计算了姐妹元素。它实际上并没有得到深度,它正在计算一个对象的所有成员。

4

6 回答 6

32

好吧,伙计,你去吧,一个完全满足你需要的功能!

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;
}

比我们想象的要容易得多。问题是它是如何递增的,它不应该递归地添加,而是获取最底部并添加一个,然后在两个兄弟姐妹之间选择最大值。

于 2012-11-23T06:14:54.040 回答
3

这个老问题最近复活了,我没有看到任何像这个一样简单的答案(公平地说,这使用了编写问题时不可用的技术):

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'}))

就像这里的大多数答案一样,当输入对象是循环的时,这将失败。解决该限制的答案需要更加复杂。

于 2021-02-05T14:46:25.327 回答
1

死而复生!将我的解决方案混合在一起-

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

于 2021-02-05T17:07:06.510 回答
0

我们可以使用注册表:

function getHowManyLevel(obj) {
  let res = JSON.stringify(obj).replace(/[^{|^}]/g, '')
  while (/}{/g.test(res)) {
    res = res.replace(/}{/g, '')
  }
  return res.replace(/}/g, '').length
}

于 2019-03-19T09:41:51.030 回答
0

如果你想保持简短,这应该做到这一点:

function maxDepth(object) {
    if (typeof object !== "object" || object === null) {
        return 0;
    }

    let values = Object.values(object);

    return (values.length && Math.max(...values.map(value => maxDepth(value)))) + 1;
}
于 2020-03-25T15:26:30.830 回答
0

我使用了一种肮脏但有效的方式:

好处是其中没有正则表达式,因为正则表达式在处理时间上很昂贵

getObjectDepth = (object) => {
      // json to array of parenthesis array: ['{','{','}','}',]
      let string = JSON.stringify(object)
          .split('')
          .filter(char => ['{', '}'].includes(char) );

      let currentDepth = 0;
      let maxDepth = 0;
      string.forEach(char => {
          if (char === '{') currentDepth++;
          if (char === '}') currentDepth--;
          if (currentDepth > maxDepth) maxDepth = currentDepth;
      });

      return maxDepth
}

它仅在对象在字符串值中没有括号时才有效。

于 2021-02-05T12:18:03.603 回答