3

I am trying to update the values in a dictionary of dictionaries of uncertain depth. This dictionary of dictionaries is loaded via h5py. As a MWE one could try:

C = {'A':{'B':12, 'C':13, 'D':{'E':20}}, 'F':14, 'G':{'H':15}}

So when I would like to set the Value of 'E' to 42 I would use

C['A']['D']['E'] = 42

This part is easy, so now lets suppose I am trying to set a value in this dict that is given by a user in the form:

([keys], value) -> e.g. (['A','D','E'], 42)

How could I set this value? Do I have to write a setter function for each possible depth?

I tried using the update function of dict like this:

def dod(keys, value):
""" Generate a dict of dicts from a list of keys and one value """
if len(keys) == 1:
    return {keys[0]: value}
else:
    return {keys[0]: dod(keys[1:], value)}

C.update(dod(['A', 'D', 'E'], 42)

But using this deletes all the elements from depth two onwards, resulting in:

C = {'A': {'D': {'E': 42}}, 'G': {'H': 15}, 'F': 14}

Did I make a mistake or is there even a simpler way of setting a value with unknown depth?

JackJadon
  • 148
  • 7

1 Answers1

2

This answer simply implements the methodology found here for your particular example:

from functools import reduce
import operator

def getFromDict(dataDict, mapList):
    return reduce(operator.getitem, mapList, dataDict)

def setInDict(dataDict, mapList, value):
    getFromDict(dataDict, mapList[:-1])[mapList[-1]] = value

C = {'A':{'B':12, 'C':13, 'D':{'E':20}}, 'F':14, 'G':{'H':15}}

setInDict(C, ['A','D','E'], 42)

print(C)

Yields:

{'A': {'B': 12, 'C': 13, 'D': {'E': 42}}, 'F': 14, 'G': {'H': 15}}
rahlf23
  • 8,869
  • 4
  • 24
  • 54