首页 > 解决方案 > 检索嵌套字典的所有键(任意长度和深度),其中键名指示字典中的位置

问题描述

假设我有以下字典:

{
'a1': {'b1': {'c1': 'val'}, 'b2': { 'c2': { 'd2': 'terminal'} } },
'a2': {'b2': 'val'}
}

我的目标是检索列表中的所有键:

'a1', 'b1', 'c1', 'b2', 'c2', 'd2', 'a2', 'b2'

但随后也保留它们在字典中的位置,如下所示:

'a1', 'a1.b1', 'a1.b1.c1', 'a1.b2', 'a1.b2.c2', 'a1.b2.c2.d2', 'a2', 'a2.b2'

这在Python中可能吗

标签: pythondictionary

解决方案


一种方法是使用递归生成器函数:

data = {
    'a1': {'b1': {'c1': 'val'}, 'b2': {'c2': {'d2': 'terminal'}}},
    'a2': {'b2': 'val'}
}


def nested_iter(d, root=""):
    for key, value in d.items():
        printable = f"{root}.{key}" if root else key
        if isinstance(value, dict):
            yield printable
            yield from nested_iter(value, root=printable)
        else:
            yield printable


print(list(nested_iter(data)))

输出

['a1', 'a1.b1', 'a1.b1.c1', 'a1.b2', 'a1.b2.c2', 'a1.b2.c2.d2', 'a2', 'a2.b2']

作为替代方案,您可以使用它collections.deque来处理递归:

def nested_iter_with_deque(d):
    from collections import deque
    result = []
    q = deque(d.items())
    while q:
        k, vs = q.popleft()
        result.append(k)
        if isinstance(vs, dict):
            lst = [(f"{k}.{key}", value) for key, value in vs.items()]
            if lst:
                q.extendleft(deque(lst))

    return result


print(nested_iter_with_deque(data))

输出

['a1', 'a1.b2', 'a1.b2.c2', 'a1.b2.c2.d2', 'a1.b1', 'a1.b1.c1', 'a2', 'a2.b2']

推荐阅读