如何在嵌套字典中查找所有出现的键,同时跟踪外部字典键值?
Posted
技术标签:
【中文标题】如何在嵌套字典中查找所有出现的键,同时跟踪外部字典键值?【英文标题】:How to find all occurrence of a key in nested dict, but also keep track of the outer dict key value? 【发布时间】:2018-07-19 03:43:22 【问题描述】:我在 *** 上进行了搜索,发现以下代码允许我递归地搜索嵌套 dict 中的键值。但是,我还想跟踪外部字典的键值。我该怎么做?
从下面链接中 Alfe 的回答中,我可以使用下面的代码获取嵌套字典中键的所有值。 Find all occurrences of a key in nested python dictionaries and lists
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
。
Find keys in nested dictionary
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
当我调用 recursive_lookup('label', data)
时,它正在返回 None
。
如果有人可以为我指出为什么上面的代码不起作用,那也太好了!
【问题讨论】:
【参考方案1】:无论您的嵌套有多深,这都应该可以工作(至少达到堆栈限制)。跟踪字典键的请求有点尴尬——我用一个元组来返回这对。请注意,如果找到的值在最外层的字典中,则不会是元组格式。
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')]
如果你想输出一个字典,这可以很容易地修改——用accumulator =
和accumulator.append((k, result))
用accumulator[k] = result
替换accumulator = []
,但这可能很难用,而且你不能存储重复关键条目。
至于你的最后一个问题,你得到None
的原因是因为内部循环returns
在检查第一项后是否找到了某些东西。由于label
位于items()
数组的第二个位置,因此它永远不会被查看。
【讨论】:
感谢@ggorlen。看起来它只返回键的第一个实例,而不是完整列表。只是想知道如何让它找到所有出现的键? 我补充说 - 根据您的问题,不确定您想要哪一个。【参考方案2】:functions 以元组列表的形式返回路径和值。
def dict_key_lookup(_dict, key, path=[]):
results = []
if isinstance(_dict, dict):
if key in _dict:
results.append((path+[key], _dict[key]))
else:
for k, v in _dict.items():
results.extend(dict_key_lookup(v, key, path= path+[k]))
elif isinstance(_dict, list):
for index, item in enumerate(_dict):
results.extend(dict_key_lookup(item, key, path= path+[index]))
return results
希望这会有所帮助。
【讨论】:
【参考方案3】:首先创建一个类似的列表
outerKeyList = []
然后,只要您想存储密钥,例如在返回要搜索的项目之前,只需运行
outerKeyList.append(key).
这将为您提供递归函数之外的所有键的方便列表。
【讨论】:
【参考方案4】:如果您的dict
中只有一个嵌套的dict
,那么您可以使用dict
理解:
In [9]: def find(label, data):
...: return outer_key: inner_val for outer_key, outer_val in data.items() for inner_key, inner_val in outer_val.items() if inner_key == label
...:
In [10]: find('label', data)
Out[10]: 'item2': 'label2', 'item3': 'label3'
【讨论】:
感谢@aydow。我确实有一个可能有不止一层的字典。但这很高兴知道!【参考方案5】:您可以使用NestedDict
from ndicts.ndicts import NestedDict
data = 'item1': 'name': 'dummy', 'type': 'dummy1',
'item2': 'label': 'label2', 'name': 'dummy', 'type': 'dummy1',
'item3': 'label': 'label3', 'name': 'dummy', 'type': 'dummy1',
'item4': 'name': 'dummy', 'type': 'dummy1'
nd = NestedDict(data)
nd_filtered= NestedDict()
for key, value in nd.items():
if "label" in key:
new_key = tuple(level for level in key if level != "label")
nd_filtered[new_key] = value
>>> nd_filtered
NestedDict('item2': 'label2', 'item3': 'label3')
>>> nd_filtered.to_dict()
'item2': 'label2', 'item3': 'label3'
您也可以考虑.extract
,尽管它不会为您提供您所要求的确切输出
>>> nd.extract["", "label"]
NestedDict('item2': 'label': 'label2', 'item3': 'label': 'label3')
安装ndictspip install ndicts
【讨论】:
以上是关于如何在嵌套字典中查找所有出现的键,同时跟踪外部字典键值?的主要内容,如果未能解决你的问题,请参考以下文章