繁体   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