python检查是否存在多个多级dict密钥



如何改进此代码或创建一个方法来检查1..N多级dict键组合?如果使用这种方法,我不清楚如何将信息传递到方法中。

try:
foo = event['key1']['key2']['key3']
except KeyError:
try:
foo = event['Key1']['Key2']
except KeyError as e::
print(f"Unable to get foo from event: {e}")
foo = "unknown"

这看起来是递归函数的完美情况。

以下函数将字典(event(、keys的有序列表和计数器变量n作为参数,在每次递归时递增。

函数在event字典中查找keys的第n个元素;如果找到键,则将相应的值分配给event变量,计数器递增,并使用新参数递归调用函数。

如果找不到关键字,或者第n个元素超出了keys的范围,或者event不再是dict类型,程序将停止并打印出event变量本身,这实际上是上一次递归中使用的关键字的值。

此外,如果在字典中找不到第一个关键字,则会显示错误。

def find_key(event, keys, n=0):
try:
event = event[keys[n]]
n += 1
find_key(event, keys, n=n)
except:
print(event if n != 0 else "The first key you provided was not found in the dictionary.")

正如您所看到的,代码的逻辑非常简单明了,例如:

event = {"key1":{"key2":{"key3":{"key4": "Hello World!"}}}}
keys = ["key1", "key2", "key3", "key4"]
find_key(event, keys)

将打印出来:

>>>Hello World!

您希望能够指定任意长度的路径并移动穿过那条路。如果你能到达路径的尽头,就返回该价值;否则,指示无法到达该路径。

def probe(dictionary, path):
first = True
# Treat the empty path [] as a reference to .
if not path:
return dictionary
for key in path:
try:
if first:
value = dictionary[key]
first = False
else:
value = value[key]
# KeyError: dictionary has key accessor but not this
# specific key.
# TypeError: The object is either not subscriptable or
# the key is not hashable.
except (KeyError, TypeError):
raise ValueError(f"The path {path} is not reachable in {dictionary}")
return value

然后你可以这样称呼它:

probe(some_dictionary, ["a", "b", "c"])

您可以这样修改签名(相应地替换对path的引用(:

def probe(dictionary, *args):

并在调用时使用更简单的语法:

probe(some_dictionary, "a", "b", "c")

这是递归函数的完美情况。下面的解决方案假设传递的列表中的第一个项目将在嵌套dict的最高级别中找到,但如果我有更多的时间,这可以很容易地解释。

def check_key_combos(d, keys: list):
if len(keys)==0:
return d
for key, val in d.items():
if key == keys[0]:
keys.pop(0)
return check_key_combos(d[key],keys)

示例:字典"d"嵌套4层,最后一层由一个数组作为值组成。

>>>d
A
1
A
1
[8 9 8]
2
[7 8 5]
3
[6 3 9]
4
[3 3 4]
B
1
[8 9 8]
2
[7 8 5]
3
[6 3 9]
4
[3 3 4]
C
1
[8 9 8]
2
[7 8 5]
3
[6 3 9]
4
[3 3 4]
2
A
1
[8 9 8]
2
[7 8 5]
3
[6 3 9]
4
[3 3 4]
B
1
[8 9 8]
2
[7 8 5]
3
[6 3 9]
4
[3 3 4]
C
1
[8 9 8]
2
[7 8 5]
3
[6 3 9]
4
[3 3 4]
>>> nested_val = check_key_combos(d,['A','2','B','4'])
>>> nested_val
array([3, 3, 4])

@ccrcvd给出了一个非常好的答案,但我不得不对其进行修改,以满足我的需求,最大限度地提高方法的功能并减少调用方的代码。这确实假设关键点在某种程度上是唯一的,所以最后一个关键点无法匹配以前的位置。

def probe(dictionary, list_of_lists, default):
for path in list_of_lists:
for key in path:
try:
value = value[key]
except UnboundLocalError:
# value needs to be instantiated
value = dictionary[key]
except (KeyError, TypeError):
print(f"The path {path} at key {key} is not reachable in {dictionary}")
break
else:
if path[-1] == key:
return value
return default

target = {
"k1": {
"k2": {
"k3": "k3 final value"
}
}
}
l1 = ["k1", "k2", "k3"]
l2 = ["k1", "k2", "k5"]
v = probe(target, [l1, l2], "default value")
print(f" value = {v}")

最新更新