簡體   English   中英

如何以pythonic方式從嵌套字典中獲取鍵

[英]How to get keys from nested dictionary in a pythonic way

我在嵌套字典中有一些項目,如果句子中的任何單詞與字典中的值匹配,我需要匹配。 如果是,則返回嵌套列表中的所有鍵。

到目前為止我已經嘗試過:

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 循環可能會變得更長。

這是一個使用遞歸的簡單方法,它沿途跟蹤鍵。 這應該說明您將如何針對任意長度執行此操作。

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

可以創建一個遞歸的 function 來跟蹤路徑,並在找到動物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])

Output:

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

注意:以上顯然不能處理所有邊緣情況,但它顯示了如何處理遞歸蠻力解決方案。 如評論中所指出的,更有效的解決方案是構建反向索引。

我喜歡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')]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM