使用Python在嵌套字典中查找键

使用Python在嵌套字典中查找键,python,python-3.x,dictionary,Python,Python 3.x,Dictionary,补充: data = { "president": { "name": "Zaphod Beeblebrox", "species": "Betelgeusian" } } 我要做的是返回名为“name”的键是否存在 这很好,但前提是我事先了解字典的结构。有没有一种方法可以知道是否有一个子键递归地称为“name”?我只找到了如何在顶层执行此操作。您可以执行递归搜索: data = { "president": { "nam

补充:

data = {
    "president": {
        "name": "Zaphod Beeblebrox",
        "species": "Betelgeusian"
    }
}
我要做的是返回名为“name”的键是否存在


这很好,但前提是我事先了解字典的结构。有没有一种方法可以知道是否有一个子键递归地称为“name”?我只找到了如何在顶层执行此操作。

您可以执行递归搜索:

data = {
    "president": {
        "name": "Zaphod Beeblebrox",
        "species": "Betelgeusian"
    }
}

def r_find(target, key):
    if key in target:
        return True
    else:
        for k, v in target.items():
            if isinstance(v, dict):
                if r_find(v, key):
                    return True
        return False


print(r_find(data, "name"))
print(r_find(data, "species"))
print(r_find(data, "no-name"))
输出

True
True
False
一种有点老套的非传统方法是使用
json.dumps
将您的
dict
转换为字符串。然后可以搜索字符串中的键

例如:

import json 

def find_key(d, key):
    if not isinstance(d, dict):
        return False
    else:
        return '"'+key+'": ' in json.dumps(d)

print(find_key(data, 'name'))
#True

一个限制是,如果您可以在一个值中包含
“name:”
,则这将不起作用。

您可以使用
try
/
定义递归生成器,但
除外:

def recursive_keys(d):
    for k, v in d.items():
        try:
            yield from recursive_keys(v)
        except AttributeError:
            yield k

'name' in set(recursive_keys(data))  # True
如果愿意,您可以使用
isinstance

def recursive_keys(d):
    for k, v in d.items():
        if isinstance(v, dict):
            yield from recursive_keys(v)
        else:
            yield k
这相对比较昂贵,因为在检查
集中是否存在项之前,首先要创建所有键的
。根据@pault的评论,您可以使用:

any(x == 'name' for x in recursive_keys(data))

有关没有生成器的惰性解决方案,请参阅。这可能更有效,因为它避免了昂贵的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?您不需要先构建整个集合来检查处于
状态的
?在@DanielMesejo的解决方案中尽早返回不是更快吗?或者可能使用
any(x==“name”表示递归键(数据)中的x)
?@pault,是的,我刚才意识到了这一点,并添加了一个递归函数,当它找到匹配项时返回
True
。但是如何使用带生成器的
any
(如我编辑的原始注释中所示)呢?这不会因为短路而使发电机加速吗?@pault,是的,说得好。我认为Daniel的解决方案会更快(生成器表达式可以更慢),但是yeh,这是一个好的解决方案。
any(x == 'name' for x in recursive_keys(data))