代码之家  ›  专栏  ›  技术社区  ›  qshng

如何在嵌套dict中找到所有出现的键,同时跟踪外部dict键的值?

  •  1
  • qshng  · 技术社区  · 6 年前

    我在stackoverflow上进行了搜索,找到了以下代码,这些代码允许我递归地在嵌套dict中搜索键值不过,我还想跟踪外部dict的键值。我该怎么做?

    从下面链接中的alfe的答案中,我可以使用下面的代码获取嵌套dict中键的所有值。 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'
    }
    

    我还发现这个链接中的递归查找写得非常整洁但是,它又回来了 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) .

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

    3 回复  |  直到 6 年前
        1
  •  1
  •   ggorlen Hoàng Huy Khánh    6 年前

    不管你的嵌套有多深(至少在堆栈的限制范围内),这都应该是可行的要求跟踪dict的密钥有点尴尬——我用了一个元组来返回这对。请注意,如果找到的值在最外面的字典中,则它将不是元组格式。

    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 = [] 具有 accumulator = {} accumulator.append((k, result)) 具有 accumulator[k] = result ,但这可能很难使用,并且不能存储重复的密钥项。

    至于你的最后一个问题 None 是因为内环 returns 在检查第一个项目是否找到了什么东西之后。自从 label 位于 items() 数组,它永远不会被看到。

        2
  •  0
  •   Jonathan Rogers    6 年前

    首先创建一个列表

    outerKeyList = []
    

    然后,当您想存储密钥时,例如在返回您正在搜索的项之前,只需运行

    outerKeyList.append(key). 
    

    这将为您提供递归函数之外的所有键的方便列表。

        3
  •  0
  •   aydow    6 年前

    如果只有一个嵌套 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'}