If I have a dict for example
d = { 'a': {
"x": [],
"y": {
"z": {
"1": 'loser'
}
}
}
}
print(d['a']['y']['z']['1']) #=> loser
However, I don't know how many nested items are in this dict. Instead I have a list of keys like:
['a', 'y', 'z', '1']
What is an elegant way to set d['a']['y']['z']['1'] = 'winner'
?
Here's what I've tried:
l = ['a', 'y', 'z', '1']
def change_the_value(d, l, value):
if len(l) == 1:
d[l[0]] = value
if len(l) == 2:
d[l[0]][l[1]] = value
if len(l) == 3:
d[l[0]][l[1]][l[2]] = value
if len(l) == 4:
d[l[0]][l[1]][l[2]][l[3]] = value
# ... ad infinitum
return d
change_the_value(d, l, 'winner')
print(d) # => {'a': {'x': [], 'y': {'z': {'1': 'winner'}}}}
You can use a simple for
loop:
_path = ['a', 'y', 'z', '1']
d = {'a': {'x': [], 'y': {'z': {'1': 'loser'}}}}
_start = d
for i in _path[:-1]:
_start = _start[i]
_start[_path[-1]] = 'winner'
print(d)
Output:
{'a': {'x': [], 'y': {'z': {'1': 'winner'}}}}
You can also use recursion (if you do not mind creating a new structure for d
):
def update(_d, _path):
return {a:'winner' if a == _path[-1] and len(_path) == 1 else
update(b, _path[1:]) if a == _path[0] else b for a, b in _d.items()}
print(update(d, ['a', 'y', 'z', '1']))
Output:
{'a': {'x': [], 'y': {'z': {'1': 'winner'}}}}
If you can be sure that the list of keys is valid, you can use functools.reduce
.
>>> from functools import reduce
>>>
>>> keys = ['a', 'y', 'z', '1']
>>> d = { 'a': {
...: "x": [],
...: "y": {
...: "z": {
...: "1": 'loser'
...: }
...: }
...: }
...: }
>>>
>>> the_dict = reduce(dict.get, keys[:-1], d)
>>> the_dict[keys[-1]] = 'winner'
>>> d
{'a': {'x': [], 'y': {'z': {'1': 'winner'}}}}
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