[英]python check multi-level dict key existence
Many SO posts show you how to efficiently check the existence of a key in a dictionary, eg, Check if a given key already exists in a dictionary许多 SO 帖子向您展示了如何有效地检查字典中是否存在键,例如, 检查给定的键是否已存在于字典中
How do I do this for a multi level key?我如何为多级密钥执行此操作? For example, if
d["a"]["b"]
is a dict, how can I check if d["a"]["b"]["c"]["d"]
exists without doing something horrendous like this:例如,如果
d["a"]["b"]
是一个字典,我如何在不做一些可怕的事情的情况下检查d["a"]["b"]["c"]["d"]
是否存在像这样:
if "a" in d and isInstance(d["a"], dict) and "b" in d["a"] and isInstance(d["a"]["b"], dict) and ...
Is there some syntax like有没有像这样的语法
if "a"/"b"/"c"/"d" in d
What I am actually using this for: we have jsons, parsed into dicts using simplejson
, that I need to extract values from.我实际使用它的目的是:我们有 json,使用
simplejson
解析成字典,我需要从中提取值。 Some of these values are nested three and four levels deep;其中一些值的嵌套深度为三层或四层; but sometimes the value doesn't exist at all.
但有时价值根本不存在。 So I wanted something like:
所以我想要这样的东西:
val = None if not d["a"]["b"]["c"]["d"] else d["a"]["b"]["c"]["d"] #here d["a"]["b"] may not even exist
EDIT: prefer not to crash if some subkey exists but is not a dictionary, eg, d["a"]["b"] = 5
.编辑:如果某些子项存在但不是字典,则不要崩溃,例如
d["a"]["b"] = 5
。
Sadly, there isn't any builtin syntax or a common library to query dictionaries like that. 遗憾的是,没有任何内置语法或公共库来查询这样的字典。
However, I believe the simplest(and I think it's efficient enough) thing you can do is: 但是,我相信最简单的(我认为它足够有效)你可以做的事情是:
d.get("a", {}).get("b", {}).get("c")
Edit: It's not very common, but there is: https://github.com/akesterson/dpath-python 编辑:这不常见,但有: https : //github.com/akesterson/dpath-python
Edit 2 : Examples: 编辑2 :示例:
>>> d = {"a": {"b": {}}}
>>> d.get("a", {}).get("b", {}).get("c")
>>> d = {"a": {}}
>>> d.get("a", {}).get("b", {}).get("c")
>>> d = {"a": {"b": {"c": 4}}}
>>> d.get("a", {}).get("b", {}).get("c")
4
This isn't probably a good idea and I wouldn't recommend using this in prod. 这可能不是一个好主意,我不建议在prod中使用它。 However, if you're just doing it for learning purposes then the below might work for you.
但是,如果您只是为了学习目的,那么下面的内容可能适合您。
def rget(dct, keys, default=None):
"""
>>> rget({'a': 1}, ['a'])
1
>>> rget({'a': {'b': 2}}, ['a', 'b'])
2
"""
key = keys.pop(0)
try:
elem = dct[key]
except KeyError:
return default
except TypeError:
# you gotta handle non dict types here
# beware of sequences when your keys are integers
if not keys:
return elem
return rget(elem, keys, default)
更新:我最终编写了自己的开源,可pippable库,允许人们这样做: https ://pypi.python.org/pypi/dictsearch
A non-recursive version, quite similar to @Meitham's solution, which does not mutate the looked-for key. 一个非递归版本,与@ Meitham的解决方案非常相似,它不会改变所查找的密钥。 Returns
True
/ False
if the exact structure is present in the source dictionary. 如果源字典中存在确切的结构,则返回
True
/ False
。
def subkey_in_dict(dct, subkey):
""" Returns True if the given subkey is present within the structure of the source dictionary, False otherwise.
The format of the subkey is parent_key:sub_key1:sub_sub_key2 (etc.) - description of the dict structure, where the
character ":" is the delemiter.
:param dct: the dictionary to be searched in.
:param subkey: the target keys structure, which should be present.
:returns Boolean: is the keys structure present in dct.
:raises AttributeError: if subkey is not a string.
"""
keys = subkey.split(':')
work_dict = dct
while keys:
target = keys.pop(0)
if isinstance(work_dict, dict):
if target in work_dict:
if not keys: # this is the last element in the input, and it is in the dict
return True
else: # not the last element of subkey, change the temp var
work_dict = work_dict[target]
else:
return False
else:
return False
The structure that is checked is in the form parent_key:sub_key1:sub_sub_key2
, where the :
char is the delimiter. 检查的结构格式为
parent_key:sub_key1:sub_sub_key2
,其中:
char是分隔符。 Obviously - it will match case-sensitively, and will stop (return False
) if there's a list within the dictionary. 显然 - 如果字典中有列表,它将区分大小写,并将停止(返回
False
)。
Sample usage: 样品用法:
dct = {'a': {'b': {'c': {'d': 123}}}}
print(subkey_in_dict(dct, 'a:b:c:d')) # prints True
print(subkey_in_dict(dct, 'a:b:c:d:e')) # False
print(subkey_in_dict(dct, 'a:b:d')) # False
print(subkey_in_dict(dct, 'a:b:c')) # True
This is what I usually use这是我经常用的
def key_in_dict(_dict: dict, key_lookup: str, separator='.'):
"""
Searches for a nested key in a dictionary and returns its value, or None if nothing was found.
key_lookup must be a string where each key is deparated by a given "separator" character, which by default is a dot
"""
keys = key_lookup.split(separator)
subdict = _dict
for k in keys:
subdict = subdict[k] if k in subdict else None
if subdict is None: break
return subdict
Returns the key if exists, or None it it doesn't如果存在则返回键,如果不存在则返回 None
key_in_dict({'test': {'test': 'found'}}, 'test.test') // 'found'
key_in_dict({'test': {'test': 'found'}}, 'test.not_a_key') // None
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.