【问题标题】:How to get the path all the keys in a list for a nested dict如何获取嵌套字典列表中所有键的路径
【发布时间】:2018-12-24 16:05:49
【问题描述】:

我想获取列表中嵌套字典的所有键的路径。例如,如果我的 dict 如下所示

{
"persons": [{
    "id": "f4d322fa8f552",
    "address": {
        "building": "710",
        "coord": "[123, 465]",
        "street": "Avenue Road",
        "zipcode": "12345"
    },
    "cuisine": "Chinese",
    "grades": [{
        "date": "2013-03-03T00:00:00.000Z",
        "grade": "B",
        "score": {
          "x": 3,
          "y": 2
        }
    }, {
        "date": "2012-11-23T00:00:00.000Z",
        "grade": "C",
        "score": {
          "x": 1,
          "y": 22
        }
    }],
    "name": "Shash"
}]
}

我想得到这样的路径 path = [['persons'], ['persons','id'],['persons','address'],['persons','address','building']...] 直到最后一个键。

我试图遍历整个字典来附加路径变量。试图从Print complete key path for all the values of a python nested dictionary 获得一些灵感,但我无法获得列表中的路径。

有没有其他可能的方法来解决这个问题。

【问题讨论】:

  • 获取path是什么意思,是递归遍历数据结构吗?你能展示你尝试过的东西吗?
  • id 实际上在persons 的列表中,而不是persons 的键作为字典。您不想考虑id 在列表中的事实吗?否则,您预期输出中的路径将毫无用处。
  • d['persons']['id'] 会产生错误,不确定是路径吗?

标签: python dictionary key


【解决方案1】:

您可以递归地描述数据结构,这是使用队列q 与递归的一种方法。但是很难判断这是否是您要查找的内容,因为它显示了列表索引,但可以很容易地排除它们:

def get_paths(d):
    q = [(d, [])]
    while q:
        n, p = q.pop(0)
        yield p
        if isinstance(n, dict):
            for k, v in n.items():
                q.append((v, p+[k]))
        elif isinstance(n, list):
            for i, v in enumerate(n):
                q.append((v, p+[i]))   # Change to q.append((v, p)) to remove index

In []:
list(get_paths(d))

Out[]:
[[],
 ['persons'],
 ['persons', 0],
 ['persons', 0, 'id'],
 ['persons', 0, 'address'],
 ['persons', 0, 'cuisine'],
 ['persons', 0, 'grades'],
 ['persons', 0, 'name'],
 ['persons', 0, 'address', 'building'],
 ['persons', 0, 'address', 'coord'],
 ['persons', 0, 'address', 'street'],
 ['persons', 0, 'address', 'zipcode'],
 ['persons', 0, 'grades', 0],
 ['persons', 0, 'grades', 1],
 ['persons', 0, 'grades', 0, 'date'],
 ['persons', 0, 'grades', 0, 'grade'],
 ['persons', 0, 'grades', 0, 'score'],
 ['persons', 0, 'grades', 1, 'date'],
 ['persons', 0, 'grades', 1, 'grade'],
 ['persons', 0, 'grades', 1, 'score'],
 ['persons', 0, 'grades', 0, 'score', 'x'],
 ['persons', 0, 'grades', 0, 'score', 'y'],
 ['persons', 0, 'grades', 1, 'score', 'x'],
 ['persons', 0, 'grades', 1, 'score', 'y'],

【讨论】:

    【解决方案2】:

    您可以将递归与生成器表达式一起使用:

    def get_paths(d, current = []):
      for a, b in d.items():
        yield current+[a]
        if isinstance(b, dict):
          yield from get_paths(b, current+[a])
        elif isinstance(b, list):
          for i in b:
            yield from get_paths(i, current+[a])
    
    final_result = list(get_paths(d))
    new_result = [a for i, a in enumerate(final_result) if a not in final_result[:i]]
    

    输出:

    [['persons'], ['persons', 'id'], ['persons', 'address'], ['persons', 'address', 'building'], ['persons', 'address', 'coord'], ['persons', 'address', 'street'], ['persons', 'address', 'zipcode'], ['persons', 'cuisine'], ['persons', 'grades'], ['persons', 'grades', 'date'], ['persons', 'grades', 'grade'], ['persons', 'grades', 'score'], ['persons', 'grades', 'score', 'x'], ['persons', 'grades', 'score', 'y'], ['persons', 'name']]
    

    【讨论】:

    猜你喜欢
    • 2014-11-27
    • 2012-05-21
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 2020-03-14
    • 1970-01-01
    • 2017-01-07
    相关资源
    最近更新 更多