如何检查物体的深度?

时间:2012-11-23 06:14:54

标签: javascript object recursion

我正在开发一个具有可变深度的权限系统;根据页面的复杂程度,可能会有更多或更少的级别。我搜索了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;
}

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

6 个答案:

答案 0 :(得分:22)

好吧,在这里,你去找好友,这个功能完全符合你的需要!

utils.depthOf = function(object) {
    var level = 1;
    var key;
    for(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;
}

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

答案 1 :(得分:1)

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

import React, { Component } from 'react';
import FeedComment from '../FeedComment/FeedComment';
import "./FeedContent.scss";

class FeedConent extends Component {

    state = {
        feedData: [],
        isLike: false,
    }

    componentDidMount() {
        fetch('http://localhost:3000/data/feedData.json', {
            method: 'GET'
        })
            .then(res => res.json())
            .then(data => {
                this.setState({
                    feedData: data
                })
            })
    }

    handleHeart = () => {
        this.setState({
            isLike: !this.state.isLike
        })
    }

    render() {
        const { feedData } = this.state;
        const { mainData } = this.props;


        return (
            <div className="feed_container">
                {feedData.map(data => {
                    return (
                        <article key={data.id} className="feed_contents">
                            <div className="feed_header">
                                <img className="round_image"
                                    src={mainData.mainImage}
                                    alt="profile" />
                                <div>
                                    <p>{mainData.mainId}</p>
                                    <p>{mainData.mainContent}</p>
                                </div>
                                <i className="fas fa-ellipsis-h settings_icon"></i>
                            </div>
                            <div className="main_image_container">
                                <img className="main-image"
                                    src={data.image}
                                    alt="purple" />
                            </div>
                            <div className="board_container">
                                <div className="icons_contianer">
                                    <i className="far fa-heart" id={this.state.isLike ? "heart_bold" : "heart_empty"} onClick={this.handleHeart}></i>
                                    <i className="far fa-comment"></i>
                                    <i className="fas fa-external-link-alt"></i>
                                    <i className="far fa-bookmark"></i>
                                </div>
                                <div className="feed_icons_container">
                                    <img className="round_image_small"
                                        src={mainData.mainImage}
                                        alt="profile" />
                                    <span> Purple and so on.... </span>
                                </div>
                                <div className="feed_message_container">
                                    <span className="feed_main_id">{mainData.mainId}</span>
                                    <span className="feed_message"> {data.content}</span>
                                </div>
                                <FeedComment />
                            </div>
                        </article>
                    )
                })}

            </div>
        );
    }
}

export default FeedConent;

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

答案 2 :(得分: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

答案 3 :(得分:0)

我们可以使用reg:

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

答案 4 :(得分: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;
}

答案 5 :(得分: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
}

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