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

时间:2020-04-07 10:59:02

标签: python python-3.x dictionary

我在嵌套词典中有一些项目,如果句子中的任何单词与词典中的值匹配,我都需要匹配。如果是这样,它将返回嵌套列表中的所有键。

到目前为止,我已经尝试过:

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']

目前,它可以满足我的需求。我想知道是否有办法以更pythonic(优雅)的方式重新编写此代码,因为如果字典中有更多要遍历的级别,则此for循环可能会更长。

3 个答案:

答案 0 :(得分:2)

这是使用递归的一种简单方法,该方法可以跟踪整个过程中的键。这应该说明您如何对任意长度执行此操作。

@application.route("/api/v1/cookies")
def set_cookie_role():
    resp = make_response('Set cookie', 200)
    resp.set_cookie('test', '12345', domain='localhost.com')
    return resp

答案 1 :(得分:1)

可以创建一个递归函数来跟踪路径,并在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']

注意:上面的方法显然不能解决所有极端情况,但是它说明了如何使用递归蛮力解决方案。如注释中指出的那样,一种更有效的解决方案是建立反向索引。

答案 2 :(得分:0)

我像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']}

您不会在任何值中找到狮子,但是去掉's'就会发现狮子

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')]