我正在开发一个具有可变深度的权限系统;根据页面的复杂程度,可能会有更多或更少的级别。我搜索了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;
}
问题在于它也是姐妹元素。它实际上没有得到深度,它正在计算一个对象的所有成员。
答案 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
}
只有当对象在字符串值中没有括号时它才有效。