如何以Python方式从嵌套字典中获取键

sulc1iza  于 2023-02-26  发布在  Python
关注(0)|答案(3)|浏览(148)

我在嵌套字典中有一些条目,我需要匹配一个句子中是否有任何单词与字典中的值匹配,如果匹配,它将返回嵌套列表中的所有键。
到目前为止我已经尝试过:

animals = {
  'vertebrates': {
    'warm_blooded': {
      'mammals': ['bear', 'tiger', 'lion'],
      'birds': ['eagle', 'ostrich', 'duck']
    },
    'cold_blooded': {
      'reptiles': ['turtle', 'crocodile'],
      'amphibians': ['frog', 'toad']
    }
  }
}

line = 'lions live in the savanna.' 

for key1, value1 in animals.items():
  for key2, value2 in value1.items():
    for key3, value3 in value2.items():
      if any(word in line for word in value3):
        print ([key1, key2, key3])

>>> ['vertebrates', 'warm_blooded', 'mammals']

目前它做了我需要的,我想知道的是,是否有一种方法,可以用更简洁的方式,重写这段代码,因为如果字典中有更多的层次需要遍历,那么for循环可能会变长。

2ic8powd

2ic8powd1#

这是一个简单的方法,使用递归跟踪键,这应该说明你如何对任意长度的键进行跟踪。

def key_match(data, to_match, found):
    for k, v in data.items():
        if isinstance(v, dict):
            key_match(v, to_match, found + [k])
        else:
            if any(word in line for word in v):
                print(found + [k])

found = []
key_match(animals, line, found)

['vertebrates', 'warm_blooded', 'mammals']
jv2fixgn

jv2fixgn2#

可以创建一个递归函数来跟踪路径,并在line中发现动物时打印路径。

def search_animals_rec(animals, line, path):
    for k, v in animals.items():
        if isinstance(v, dict):
            search_animals_rec(v, line, path + [k])
        elif isinstance(v, list):
            for animal in v:
                if animal in line:
                    print(path + [k])

search_animals_rec(animals, line, [])

或者使用any()

def search_animals_rec(animals, line, path):
    for k, v in animals.items():
        if isinstance(v, dict):
            search_animals_rec(v, line, path + [k])
        elif isinstance(v, list):
            if any(animal in line for animal in v):
                print(path + [k])

输出:

['vertebrates', 'warm_blooded', 'mammals']

**注意:**以上显然不能处理所有的边缘情况,但它展示了如何使用递归暴力破解方法。更有效的解决方案是构建一个倒排索引,如注解中所指出的。

j2qf4p5b

j2qf4p5b3#

我喜欢的flatten-dict模块,可能会派上用场的几个操作:

from flatten_dict import flatten
flat = flatten(animals)
print(flat)

{('vertebrates', 'warm_blooded', 'mammals'): ['bear', 'tiger', 'lion'],
 ('vertebrates', 'warm_blooded', 'birds'): ['eagle', 'ostrich', 'duck'],
 ('vertebrates', 'cold_blooded', 'reptiles'): ['turtle', 'crocodile'],
 ('vertebrates', 'cold_blooded', 'amphibians'): ['frog', 'toad']}

你不会在任何一个值中找到lions,但是去掉"s“,你会找到lion:

line = 'lion live in the savanna.'
#used a set to avoid duplication
words = set(line.strip('.').split())
print(words)
{'in', 'lion', 'live', 'savanna', 'the'}

[key for word in words for key,value in flat.items() if word in value ]

[('vertebrates', 'warm_blooded', 'mammals')]

相关问题