Search code examples
pythondictionarynested

Recursively replacing or updating key value pairs in a nested dictionary


Say I have a dictionary like this:

mydict = {
  "name": "Bill", 
  "gender": "Male", 
  "facts": {"age": 20, "location": "England"}
}

so it contains another dictionary as a value. Now suppose I have this dictionary:

to_replace = {"name": "Billy Kidman", "gender": "Female"}

and I want to update mydict to reflect this new information. To do that I use

from dataclasses import replace
mydict = replace(mydict, **to_replace)

and this works, because now it looks like

mydict = {
  "name": "Billy Kidman", 
  "gender": "Female", 
  "facts": {"age": 20, "location": "England"}
}

Now suppose I want to update mydict with the following information:

to_replace_2 = {"name": "Billy Kidman", "gender": "Female", "age": 55}

Then I can't use replace as above, because age is not key of mydict but it's actually a key of a value. Python throws an error if I try to do this. How can I do this correctly? I have no freedom in the form of to_replace_2; it is how I wrote it above and I can't change that. Is there a way to make replace do what I want it to do, to find all the keys that need to be replaced no matter if they're nested and make the changes?


Solution

  • Try:

    def replace(o, to_replace):
        if isinstance(o, dict):
            common_keys = o.keys() & to_replace.keys()
            for k in common_keys:
                o[k] = to_replace[k]
    
            for v in o.values():
                replace(v, to_replace)
    
        elif isinstance(o, list):
            for v in o:
                replace(v, to_replace)
    
    
    mydict = {"name": "Bill", "gender": "Male", "facts": {"age": 20, "location": "England"}}
    to_replace_2 = {"name": "Billy Kidman", "gender": "Female", "age": 55}
    
    replace(mydict, to_replace_2)
    
    print(mydict)
    

    Prints:

    {'name': 'Billy Kidman', 'gender': 'Female', 'facts': {'age': 55, 'location': 'England'}}