首页 > 解决方案 > 如何在嵌套字典中查找所有出现的键,同时跟踪外部字典键值?

问题描述

我搜索了 stackoverflow 并找到了以下代码,这些代码允许我递归地搜索嵌套 dict 中的键值。但是,我还想跟踪外部字典的键值。我该怎么做?

从下面链接中 Alfe 的回答中,我可以使用下面的代码获取嵌套字典中键的所有值。 在嵌套的 Python 字典和列表中查找所有出现的键

data = {'item1': {
  'name': 'dummy',
  'type': 'dummy1'},

'item2': {
  'name': 'dummy',
  'type': 'dummy1',
  'label':'label2'
},

'item3': {
  'name': 'dummy',
  'type': 'dummy1',
  'label':'label3'},

'item4': {
  'name': 'dummy',
  'type': 'dummy1'}
}

 def find(key, dictionary):
    for k, v in dictionary.items():
        if k == key:
            yield v
        elif isinstance(v, dict):
            for result in find(key, v):
                yield result
        elif isinstance(v, list):
            for d in v:
                for result in find(key, d):
                    yield result


In[1]:list(find('label', data))
Out[1]: 
['label2', 'label3']

但是,我还需要记录外部 dict 键,如下所示。我该怎么做?此外,我的数据可能有不止一层。

{'item2':'label2',
'item3':'label3'
}

我还发现此链接中的 recursive_lookup 写得非常整齐。None但是,当我尝试运行它时它又回来了。

在嵌套字典中查找键

def recursive_lookup(k, d):
    if k in d:
        return d[k]
    for v in d.values():
        if isinstance(v, dict):
            return recursive_lookup(k, v)
    return None

None当我打电话时它正在返回recursive_lookup('label', data)

如果有人可以为我指出为什么上面的代码不起作用,那也太好了!

标签: pythondictionarynested

解决方案


无论您的嵌套有多深(无论如何都达到堆栈限制),这都应该有效。跟踪字典键的请求有点尴尬——我用一个元组来返回这对。请注意,如果找到的值在最外层的字典中,则它不会是元组格式。

def recursive_lookup(key, d):
    if key in d:
        return d[key]

    for k, v in d.items():
        if isinstance(v, dict):
            result = recursive_lookup(key, v)

            if result:
                return k, result


print(recursive_lookup('label', data))

输出:

('item2', 'label2')

这是一个有点混乱的版本(我对内部函数并不着迷,但至少累加器列表不是参数,也不是全局的),但会返回嵌套到堆栈限制的所有已找到项目的列表,除了最外面的键:

def recursive_lookup(key, d):
    def _lookup(key, d):
        if key in d:
            return d[key]

        for k, v in d.items():
            if isinstance(v, dict):
                result = _lookup(key, v)

                if result:
                    accumulator.append((k, result))

    accumulator = []
    _lookup(key, d)
    return accumulator

输出:

[('item3', 'label3'), ('item2', 'label2')]

如果您想输出 dict--replace accumulator = []withaccumulator = {}accumulator.append((k, result))with accumulator[k] = result,这可以很容易地修改,但这可能很难使用,并且您不能存储重复的键条目。

至于你的最后一个问题,你得到的原因None是因为在检查第一项之后的内部循环returns是否找到了某些东西。由于label位于items()数组的第二个位置,因此它永远不会被查看。


推荐阅读