Suppose I have a dictionary that is nested arbitrarily:
d = {
11: {
21: {31: 'a', 32: 'b'},
22: {31: 'a', 34: 'c'},
},
12: {
1: {2: 3}
}
}
And a list of keys whose position tells me which nested dictionary to look for every key in:
keys = [11, 21, 31]
# keys = [11, 23, 44]
Is there a simple one liner to do this? I've looked at the questions listed below, and they are similar, but not really what I'm looking for. I have also attempted it myself and came up with this:
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'
The problem with this, is that in case of second list of keys (see commented out keys), it continues looking up nested keys further, even though the higher level key wasn't found, and continuing is pointless. How can I stop reduce
as soon as I find a final match or fail (one of the questions listed below addresses it, but I can't really apply it in my use case... or can I?)? Any other ideas? Oh and I want to accomplish this using official python libraries only. So no numpy
, pandas
etc, but functools
, itertools
are fine
Python: Convert list to dict keys for multidimensional dict with exception handling
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
Thanks!
Access Values using get() Another way to access value(s) in a nested dictionary ( employees ) is to use the dict. get() method. This method returns the value for a specified key. If the specified key does not exist, the get() method returns None (preventing a KeyError ).
You can access individual items in a nested dictionary by specifying key in multiple square brackets. If you refer to a key that is not in the nested dictionary, an exception is raised.
d = {'a':1,'b':1,'c':2}; "". join([k+str(v) for k,v in d.
You can use 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'
For the keys you mentioned, it goes like this:
dict.get
with d
(initial) and the first item of keys
(11
) to get d[11]
dict.get
with the result (a dictionary) and the next item in keys
(21
) to get {...}[21]
dict.get
...until keys
is "reduced" to the final value ('a'
)
Edit: As dict.get
results in None
if there is no such key, there might be undesired results. If you want to have a KeyError
, you can use operator.getitem
instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With