在嵌套的Python字典中搜索并记录"path". [英] Search in nested Python dict and record "path"

查看:63
本文介绍了在嵌套的Python字典中搜索并记录"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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆