簡體   English   中英

如何在Python中的嵌套字典中檢查值?

[英]How do I check value in a nested dictionary in Python?

假設我們有一個字典listD的列表,其中每個字典都嵌套了很多字典。 例如,假設listD的第一個元素是:

listD[0] = {"bar1":{"bar2":{"bar3":1234}}}

現在,我要檢查listD [i] [“ bar1”] [“ bar2”] [“ bar3”] == 1234是否適用於所有i。 對於i = 0的第一個元素,這很容易,因為我們可以使用以下表達式:

listD[0]["bar1"]["bar2"]["bar3"] == 1234 

但是我不能簡單地寫一個像這樣的循環:

for dictelem in listD:
  if dictelem["bar1"]["bar2"]["bar3"] == 1234:
    print "equals 1234"

這是因為listD的某些字典元素可能具有以下形式:

listD[i] = {"bar1":{"bar2":"abcd"}} or
listD[i] = {"bar1":{"bar2":None}} 

如果我嘗試訪問不存在的“ bar3”,則會出現錯誤。

現在,我在代碼中手動指定要檢查bar1,bar2和bar3鍵的存在以及它們是否實際上是字典。 但這確實很冗長,我很確定有一種簡單的方法可以做到,但是我不知道怎么做。

def dictcheck(d, p, v):
    if len(p):
        if isinstance(d,dict) and p[0] in d:
            return dictcheck(d[p[0]], p[1:], v)
    else:
        return d == v

您傳遞一個dict d ,一個鍵p路徑以及最終值以檢查v 它將遞歸地輸入字典,最后檢查最后一個值是否等於v

>>> dictcheck({"bar1":{"bar2":{"bar3":1234}}}, ('bar1','bar2','bar3'), 1234)
True

>>> dictcheck({"bar1":1234}, ('bar1','bar2','bar3'), 1234)
False

因此,回答您的問題( 我想檢查listD [i] [“ bar1”] [“ bar2”] [“ bar3”] == 1234是否代表所有i ):

all(dictcheck(x, ('bar1','bar2','bar3'), 1234) for x in listD)

只是這樣使用try/except塊:

for dictelem in listD:
    try:
        if dictelem["bar1"]["bar2"]["bar3"] == 1234:
            print "equals 1234"
    except TypeError:
        pass

在處理嵌套字典時,我將它們視為一棵樹,其中的鍵構成了通往值的路徑。 考慮到這一點,我創建了一個非遞歸函數dict_pathdict_path帶有一個嵌套字典,鍵路徑和一個值(如果找不到):

def dict_path(dic, path, value_if_not_found=None):
    path = path.split('.')
    try:
        for key in path:
            dic = dic[key]
        return dic
    except (KeyError, TypeError):
        return value_if_not_found

listD = [
    {"bar1": {"bar2": 'abcd'}},
    {"bar1": {"bar2": None}},
    {"bar1": {"bar2": {"bar3": 1234}}},
]

for dic in listD:
    value = dict_path(dic, 'bar1.bar2.bar3')
    if value == 1234:
        print 'Equals 1234:', dic

該函數將繼續遍歷嵌套字典,直到出現以下三種情況之一:

  1. 它發現了有問題的價值。 在這種情況下,返回該值
  2. 在此過程中,對象是字典,但沒有請求的鍵。 在這種情況下,會引發KeyError
  3. 該對象不是字典, TypeError

對於情況2和3,我們只返回value_if_not_found

你可以試試這個

for item in listD:
    if item.get("bar1",{}).get("bar2",{}).get("bar3","") == 1234:
        print "yeah, gotcha"

暫無
暫無

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

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