从嵌套的字典中获取父键

12
从下面的嵌套字典中,我该如何获取每个包含'value4ac'的父字典键?通过查找'value4ac'值,我想得到'key4'、'key4a'、'Key4ac'。
example_dict = { 'key1' : 'value1',
                 'key2' : 'value2',
                 'key3' : { 'key3a': 'value3a' },
                 'key4' : { 'key4a': { 
                                         'key4aa': 'value4aa',
                                         'key4ab': 'value4ab',
                                         'key4ac': 'value4ac'
                                     },
                            'key4b': 'value4b'
                           }
                   } 

关于键名,有逻辑可言吗?我的意思是,您知道'key4ac'将被key4所引用的dict中吗? - Bakuriu
4个回答

20

递归来解救!

example_dict = { 'key1' : 'value1',
                 'key2' : 'value2',
                 'key3' : { 'key3a': 'value3a' },
                 'key4' : { 'key4a': { 'key4aa': 'value4aa',
                                       'key4ab': 'value4ab',
                                       'key4ac': 'value4ac'},
                            'key4b': 'value4b'}
                }

def find_key(d, value):
    for k,v in d.items():
        if isinstance(v, dict):
            p = find_key(v, value)
            if p:
                return [k] + p
        elif v == value:
            return [k]

print find_key(example_dict,'value4ac')

工作原理

它查看项目并检查两种情况

  • 项目不是字典--在这种情况下,看看它是否是我们正在寻找的值。如果是,则返回一个仅包含键的列表。(这是递归的基本情况)。
  • 项目是字典--尝试在该字典中查找键。如果在该字典(或任何子字典)中找到它,则返回将正确路径前缀添加到其余路径上的键。

你的意思是通过 def find_key(d,key): 来查找值,应该改为 def find_key(d,value):,对吗? - zelusp
@zelusp -- 是的,那个变量的名字很不幸。:-)。谢谢你的建议。 - mgilson
如何查找多个出现次数?例如,具有关键路径的列表列表。例如: [['key4','key4a','key4ac'],['key5','key5a','key5ac']] - Blind0ne

9

如果你的字典中也包含列表怎么办?

以下是@mgilson解决方案的更广泛变体,适用于JSON:

example_dict_with_list = { 'key1' : 'value1',
                           'key2' : 'value2',
                           'key3' : { 'key3a': 'value3a' },
                           'key4' : { 'key4a': [{ 'key4aa': 'value4aa',
                                                  'key4ab': 'value4ab',
                                                  'key4ac': 'value4ac'}],
                                      'key4b': 'value4b'}
                          }

def breadcrumb(json_dict_or_list, value):
  if json_dict_or_list == value:
    return [json_dict_or_list]
  elif isinstance(json_dict_or_list, dict):
    for k, v in json_dict_or_list.items():
      p = breadcrumb(v, value)
      if p:
        return [k] + p
  elif isinstance(json_dict_or_list, list):
    lst = json_dict_or_list
    for i in range(len(lst)):
      p = breadcrumb(lst[i], value)
      if p:
        return [str(i)] + p

print(
    breadcrumb(example_dict_with_list, 'value4aa')
)

返回值

['key4', 'key4a', '0', 'key4aa', 'value4aa']

奖金

如果您需要将其漂亮地打印出来,就像一串面包屑字符串一样,请执行以下操作:

print(
  ' > '.join(
    breadcrumb(example_dict, 'value4aa')
  )
)

这个将返回

'key4 > key4a > 0 > key4aa > value4aa'

一个完美的答案!对我来说,应该更清晰一些 def breadcrumb(json_dict_or_list, value) -> list:p: list = breadcrumb(v, value) - lam vu Nguyen

0

支持字典键和列表元素的解决方案

对@KiriSakow方案(受@mgilson启发)进行了轻微修改。

它不会产生列表索引,并且不仅为最后一个子项返回正确的父级,而且还为子父级返回正确的父级。

def breadcrumb(nested_dict, value):
    if nested_dict == value:
        return [nested_dict]
    elif isinstance(nested_dict, dict):
        for k, v in nested_dict.items():
            if k == value:
                return [k]
            p = breadcrumb(v, value)
            if p:
                return [k] + p
    elif isinstance(nested_dict, list):
        lst = nested_dict
        for i in range(len(lst)):
            p = breadcrumb(lst[i], value)
            if p:
                return p

输入

example_dict_with_list = { 'key1' : 'value1',
                           'key2' : 'value2',
                           'key3' : { 'key3a': 'value3a' },
                           'key4' : { 'key4a': [{ 'key4aa': 'value4aa',
                                                  'key4ab': 'value4ab',
                                                  'key4ac': 'value4ac'}],
                                      'key4b': 'value4b'}
                          }


print(breadcrumb(example_dict_with_list, "value4aa"))
print(breadcrumb(example_dict_with_list, "key4aa"))

输出

['key4', 'key4a', 'key4aa', 'value4aa']
['key4', 'key4a', 'key4aa']

0
你可以使用一个 NestedDict
>>> from ndicts.ndicts import NestedDict
>>> example_dict = { 'key1' : 'value1',
...                  'key2' : 'value2',
...                  'key3' : { 'key3a': 'value3a' },
...                  'key4' : { 'key4a': {
...                                          'key4aa': 'value4aa',
...                                          'key4ab': 'value4ab',
...                                          'key4ac': 'value4ac'
...                                      },
...                             'key4b': 'value4b'
...                            }
...                    }
>>> nd = NestedDict(example_dict)
>>> for key, value in nd.items():
...     if value == "value4ac":
...             print(key)
...
('key4', 'key4a', 'key4ac')

安装ndicts

pip install ndicts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接