How to set “nth” element of a nested python dict with given list location?

  • A+
Category:Languages

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'}}}} 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: