一种从字典中查找嵌套值的方法 python
One liner to look up nested value from a dictionary python
假设我有一个任意嵌套的字典:
d = {
11: {
21: {31: 'a', 32: 'b'},
22: {31: 'a', 34: 'c'},
},
12: {
1: {2: 3}
}
}
还有一个键列表,其位置告诉我在哪个嵌套字典中查找每个键:
keys = [11, 21, 31]
# keys = [11, 23, 44]
是否有一个简单的衬垫可以做到这一点?我查看了下面列出的问题,它们很相似,但并不是我真正想要的。我自己也尝试过并想出了这个:
from functools import reduce
def lookup(d, key):
return d.get(key, {}) if d and isinstance(d, dict) else None
def fn(keys, d):
return reduce(lookup, keys, d)
print(fn(keys, d)) # prints 'a'
这个问题是,如果是第二个键列表(请参阅注释掉的键),它会继续进一步查找嵌套键,即使没有找到更高级别的键,并且继续是没有意义的。如何在找到最终匹配项或失败后立即停止 reduce
(下面列出的问题之一解决了它,但我不能真正将其应用到我的用例中......或者我可以吗?)?还有其他想法吗?哦,我只想使用官方 python 库来完成此操作。所以没有 numpy
、pandas
等,但是 functools
、itertools
很好
Is there a simple one-liner for accessing each element of a nested dictioanry in Python?
Accessing nested values in nested dictionaries in Python 3.3
Using itertools for recursive function application
Stopping a Reduce() operation mid way. Functional way of doing partial running sum
Finding a key recursively in a dictionary
谢谢!
您可以使用 functools.reduce()
:
from functools import reduce # In Python 2, don't import it. (It's a built-in)
print(reduce(dict.get, keys, d))
# 'a'
对于您提到的键,它是这样的:
- 用
d
(初始)和keys
(11
)的第一项调用dict.get
得到d[11]
- 调用
dict.get
结果(字典)和 keys
中的下一项 (21
) 得到 {...}[21]
- 呼叫
dict.get
...
...
直到 keys
是 "reduced" 到最终值 ('a'
)
Edit: 由于 dict.get
导致 None
如果没有这样的键,可能会出现不希望的结果。如果你想要KeyError
,你可以使用operator.getitem
代替。
d = {
11: {
21: {
31: 'a from dict'
},
},
}
l = [None] * 50
l[11] = [None] * 50
l[11][21] = [None] * 50
l[11][21][31] = 'a from list'
from functools import reduce
goodkeys = [11, 21, 31]
badkeys = [11, 12, 13]
print("Reducing dictionary (good):", reduce(lambda c,k: c.__getitem__(k), goodkeys, d))
try:
print("Reducing dictionary (bad):", reduce(lambda c,k: c.__getitem__(k), badkeys, d))
except Exception as ex:
print(type(ex), ex)
print("Reducing list (good):", reduce(lambda c,k: c.__getitem__(k), goodkeys, l))
try:
print("Reducing list (bad):", reduce(lambda c,k: c.__getitem__(k), badkeys, l))
except Exception as ex:
print(type(ex), ex)
这是我想出的一个解决方案,当给定一个无效的查找路径时,它也会返回有用的信息,并允许您挖掘任意 json,包括嵌套列表和字典结构。 (抱歉,这不是 one-liner)。
def get_furthest(s, path):
'''
Gets the furthest value along a given key path in a subscriptable structure.
subscriptable, list -> any
:param s: the subscriptable structure to examine
:param path: the lookup path to follow
:return: a tuple of the value at the furthest valid key, and whether the full path is valid
'''
def step_key(acc, key):
s = acc[0]
if isinstance(s, str):
return (s, False)
try:
return (s[key], acc[1])
except LookupError:
return (s, False)
return reduce(step_key, path, (s, True))
假设我有一个任意嵌套的字典:
d = {
11: {
21: {31: 'a', 32: 'b'},
22: {31: 'a', 34: 'c'},
},
12: {
1: {2: 3}
}
}
还有一个键列表,其位置告诉我在哪个嵌套字典中查找每个键:
keys = [11, 21, 31]
# keys = [11, 23, 44]
是否有一个简单的衬垫可以做到这一点?我查看了下面列出的问题,它们很相似,但并不是我真正想要的。我自己也尝试过并想出了这个:
from functools import reduce
def lookup(d, key):
return d.get(key, {}) if d and isinstance(d, dict) else None
def fn(keys, d):
return reduce(lookup, keys, d)
print(fn(keys, d)) # prints 'a'
这个问题是,如果是第二个键列表(请参阅注释掉的键),它会继续进一步查找嵌套键,即使没有找到更高级别的键,并且继续是没有意义的。如何在找到最终匹配项或失败后立即停止 reduce
(下面列出的问题之一解决了它,但我不能真正将其应用到我的用例中......或者我可以吗?)?还有其他想法吗?哦,我只想使用官方 python 库来完成此操作。所以没有 numpy
、pandas
等,但是 functools
、itertools
很好
Is there a simple one-liner for accessing each element of a nested dictioanry in Python?
Accessing nested values in nested dictionaries in Python 3.3
Using itertools for recursive function application
Stopping a Reduce() operation mid way. Functional way of doing partial running sum
Finding a key recursively in a dictionary
谢谢!
您可以使用 functools.reduce()
:
from functools import reduce # In Python 2, don't import it. (It's a built-in)
print(reduce(dict.get, keys, d))
# 'a'
对于您提到的键,它是这样的:
- 用
d
(初始)和keys
(11
)的第一项调用dict.get
得到d[11]
- 调用
dict.get
结果(字典)和keys
中的下一项 (21
) 得到{...}[21]
- 呼叫
dict.get
...
...
直到 keys
是 "reduced" 到最终值 ('a'
)
Edit: 由于 dict.get
导致 None
如果没有这样的键,可能会出现不希望的结果。如果你想要KeyError
,你可以使用operator.getitem
代替。
d = {
11: {
21: {
31: 'a from dict'
},
},
}
l = [None] * 50
l[11] = [None] * 50
l[11][21] = [None] * 50
l[11][21][31] = 'a from list'
from functools import reduce
goodkeys = [11, 21, 31]
badkeys = [11, 12, 13]
print("Reducing dictionary (good):", reduce(lambda c,k: c.__getitem__(k), goodkeys, d))
try:
print("Reducing dictionary (bad):", reduce(lambda c,k: c.__getitem__(k), badkeys, d))
except Exception as ex:
print(type(ex), ex)
print("Reducing list (good):", reduce(lambda c,k: c.__getitem__(k), goodkeys, l))
try:
print("Reducing list (bad):", reduce(lambda c,k: c.__getitem__(k), badkeys, l))
except Exception as ex:
print(type(ex), ex)
这是我想出的一个解决方案,当给定一个无效的查找路径时,它也会返回有用的信息,并允许您挖掘任意 json,包括嵌套列表和字典结构。 (抱歉,这不是 one-liner)。
def get_furthest(s, path):
'''
Gets the furthest value along a given key path in a subscriptable structure.
subscriptable, list -> any
:param s: the subscriptable structure to examine
:param path: the lookup path to follow
:return: a tuple of the value at the furthest valid key, and whether the full path is valid
'''
def step_key(acc, key):
s = acc[0]
if isinstance(s, str):
return (s, False)
try:
return (s[key], acc[1])
except LookupError:
return (s, False)
return reduce(step_key, path, (s, True))