【问题标题】:How to find the maximum "depth" of a python dictionary or JSON object?如何找到 python 字典或 JSON 对象的最大“深度”?
【发布时间】:2015-09-04 20:34:56
【问题描述】:

我有一个 json 字符串,我想知道它的最大深度是多少。深度是指嵌入键的数量。因此,如果一个键作为 7 个“孩子”并且知道其他键有那么多,那么深度将是 8。

由于唯一可以嵌入其他对象的类型(我相信)是数组和其他字典,因此需要检查所有这些。有没有办法检查这个?

我希望在没有外部模块的情况下实现这一目标,但如果没有,我将瞄准 python3。

注意:这就是我所说的“深度”

以下词典:

{
  "path": "/0001_Anthem",
  "name": "0001_Anthem",
  "isMovie": true,
  "runtime": 3600,
  "thumbnailLocation": "/thubs/test.png",
  "id": 1, 
  "media": [
    {
      "path": "/0001_Anthem/louvers.mp4",
      "name": "louvers.mp4"
    }
  ]
}

会有一个“深度”或长度为 3,因为最远的嵌入项是 media 数组(第 2 级)中的键/值对(第 3 级),在主 dictionary(第 1 级)中)。我不确定其他人使用什么术语,这只是我认为有意义的术语。

谢谢

【问题讨论】:

  • 你能更详细地解释一下你所说的深度是什么意思吗?这听起来不像通常的定义。也许有一些例子?
  • 如果您说“数组和字典”,您是否可能指向collections.Mappingcollections.Sequence
  • @Blorgbeard 澄清
  • 好吧,这实际上是通常的定义,我只是被你的措辞弄糊涂了 :)

标签: python json dictionary


【解决方案1】:

这是一个实现:

def depth(x):
    if type(x) is dict and x:
        return 1 + max(depth(x[a]) for a in x)
    if type(x) is list and x:
        return 1 + max(depth(a) for a in x)
    return 0

【讨论】:

  • 不能测试这个{'children': [{'name': 'product service', 'children': [{'name': 'price', 'children': [{'name': 'cost', 'size': 8}]}, {'name': 'quality', 'children': [{'name': 'messaging', 'size': 4}]}]}, {'name': 'customer service', 'children': [{'name': 'Personnel', 'children': [{'name': 'CEO', 'size': 7}]}]}, {'name': 'product', 'children': [{'name': 'Apple', 'children': [{'name': 'iPhone 4', 'size': 10}]}]}]}
  • @jayprakashstar,您能否解释一下为什么您认为它不起作用?根据@Startec 的原始问题 and 定义,您的示例是深度 7。如果您漂亮地打印您的示例,您会看到最大缩进级别(所有键 namesize)正好是 7。
【解决方案2】:
def depth(d):
    if hasattr(d, "values"):
        return 1 + max(map(depth, d.values()))
    if hasattr(d, "__len__") and not hasattr(d, "lower"):
        return 1 + max(map(depth, d))
    return 0

【讨论】:

    【解决方案3】:

    仔细查看您的 Q,您想从 JSON 字符串 中获取深度。这是我写的一个函数:

    # This function count list/dict/tuple as levels
    def get_json_depth(s):
        d = {"(":")", "[":"]", "{":"}" }
        stack = []
        lefts = d.keys()
        rights = d.values()
    
        max_depth = 0
        depth = 0
        in_quotes = False
    
        for c in s:
                if c == '"':
                        in_quotes = not in_quotes
                if not in_quotes:
                        if c in lefts:
                                stack.append(c)
                                depth += 1
                                if depth > max_depth:
                                        max_depth = depth
                        elif c in rights:
                                if not stack:
                                        raise Exception()
                                if c != d[stack.pop()]:
                                        raise Exception()
        return max_depth
    

    但如果您不介意使用json.loads(s) 将其转换为字典,那么请使用@Blorgbeard 的递归函数。

    【讨论】:

      【解决方案4】:

      您可以像这样使用递归函数找到深度。

      def depth(jsnFile):
          if jsnFile.has_key('children'):
             return 1 +  max([0] + map(depth, jsnFile['children']))
          else:
             return 1
      

      【讨论】:

      • 我的意思是一个键名未知的字典(甚至键名都不知道)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多