在嵌套的Python字典中搜索并记录"path". [英] Search in nested Python dict and record "path"
问题描述
借助此 answer ,我正在尝试提出一个功能,该功能在键入以下内容时进行搜索嵌套的Python字典,并记录每个匹配项的路径".我的函数(见下文)似乎起作用,但是无法将结果保存在列表中(见代码输出).我可以肯定,困难在于yield
命令,但是我还无法弄清楚.
With the help of this answer, I'm trying to come up with a function that searches after a key in a nested Python dict and also records the "path" of each match. My function (see below) seems to work, however it is not possible to save the result in a list (see code output). I'm pretty certain that the difficulty lies in the yield
command, but I have not been able to figure it out yet.
o={
'dict1': {
'dict11': {
'entry11_1':1,
'entry11_2':2,
},
'dict12': {
'entry12_1':12,
'entry12_2':22,
},
},
'dict2': {
'dict21': {
'entry21_1':21,
}
},
}
curr_pos=[]
def gen_dict_extract(key, var):
global curr_pos
if hasattr(var,'iteritems'):
for k, v in var.iteritems():
#print curr_pos
if k == key:
yield v,curr_pos
if isinstance(v, dict):
curr_pos.append(k)
for result in gen_dict_extract(key, v):
yield result
elif isinstance(v, list):
for d in v:
for result in gen_dict_extract(key, d):
yield result
if len(curr_pos)>0:
curr_pos.pop()
result_list=[]
for ind,i in enumerate(gen_dict_extract('entry12_1',o)):
result_list.append(i)
print result_list[-1]
print result_list[-1]
输出:
(12, ['dict1', 'dict12'])
(12, [])
推荐答案
在gen_dict_extract
中,您使用全局列表curr_pos
,并在找到键(yield v,curr_pos
)后直接产生它.但是列表是可变类型,您稍后可以对其进行修改(curr_pos.pop()
)
In gen_dict_extract
you use a global list curr_pos
and directly yield it when you have found the key (yield v,curr_pos
). But a list is a mutable type, and you later modify it (curr_pos.pop()
)
您存储在result_list中的内容只是对全局对象的引用,因此它包含循环内的期望值,但在循环结束时将其清空.您应该只在屈服时返回一个浅表副本:yield v,curr_pos[:]
What you have stored in result_list is just a reference to the global object, so it contains the expected value inside the loop, but is emptied at the end of the loop. You should just return a shallow copy at yield time: yield v,curr_pos[:]
然后您将获得预期的结果:
You will then get as expected:
(12, ['dict1', 'dict12'])
(12, ['dict1', 'dict12'])
顺便说一句,要避免使用全局列表,可以将列表作为可选参数传递
BTW, it you want to avoid a global list, you could pass the list as an optional parameter:
def gen_dict_extract(key, var, curr_pos = None):
if curr_pos is None:
curr_pos = []
...
for result in gen_dict_extract(key, v, curr_pos):
...
for result in gen_dict_extract(key, d, curr_pos):
...
这将确保您在每次新调用时使用一个新列表,同时在递归时正确传递它
That would ensure that you use a new list on each fresh invocation, while correctly passing it when recursing
这篇关于在嵌套的Python字典中搜索并记录"path".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!