17

I am trying to update values in a nested dictionary, without over-writting previous entries when the key already exists. For example, I have a dictionary:

  myDict = {}
  myDict["myKey"] = { "nestedDictKey1" : aValue }

giving,

 print myDict
>> { "myKey" : { "nestedDictKey1" : aValue }}

Now, I want to add another entry , under "myKey"

myDict["myKey"] = { "nestedDictKey2" : anotherValue }}

This will return:

print myDict
>> { "myKey" : { "nestedDictKey2" : anotherValue }}

But I want:

print myDict
>> { "myKey" : { "nestedDictKey1" : aValue , 
                 "nestedDictKey2" : anotherValue }}

Is there a way to update or append "myKey" with new values, without overwriting the previous ones?

eric
  • 301
  • 1
  • 4
  • 14

7 Answers7

19

This is a very nice general solution to dealing with nested dicts:

import collections
def makehash():
    return collections.defaultdict(makehash)

That allows nested keys to be set at any level:

myDict = makehash()
myDict["myKey"]["nestedDictKey1"] = aValue
myDict["myKey"]["nestedDictKey2"] = anotherValue
myDict["myKey"]["nestedDictKey3"]["furtherNestedDictKey"] = aThirdValue

For a single level of nesting, defaultdict can be used directly:

from collections import defaultdict
myDict = defaultdict(dict)
myDict["myKey"]["nestedDictKey1"] = aValue
myDict["myKey"]["nestedDictKey2"] = anotherValue

And here's a way using only dict:

try:
  myDict["myKey"]["nestedDictKey2"] = anotherValue
except KeyError:
  myDict["myKey"] = {"nestedDictKey2": anotherValue}
Allen Luce
  • 7,859
  • 3
  • 40
  • 53
10

You can use collections.defaultdict for this, and just set the key-value pairs within the nested dictionary.

from collections import defaultdict
my_dict = defaultdict(dict)
my_dict['myKey']['nestedDictKey1'] = a_value
my_dict['myKey']['nestedDictKey2'] = another_value

Alternatively, you can also write those last 2 lines as

my_dict['myKey'].update({"nestedDictKey1" : a_value })
my_dict['myKey'].update({"nestedDictKey2" : another_value })
Stuart
  • 9,597
  • 1
  • 21
  • 30
2

You could treat the nested dict as immutable:

myDict["myKey"] = dict(myDict["myKey"], **{ "nestedDictKey2" : anotherValue })

Albert James Teddy
  • 1,336
  • 1
  • 13
  • 24
2

You can write a generator to update key in nested dictionary, like this.

def update_key(key, value, dictionary):
        for k, v in dictionary.items():
            if k == key:
                dictionary[key]=value
            elif isinstance(v, dict):
                for result in update_key(key, value, v):
                    yield result
            elif isinstance(v, list):
                for d in v:
                    if isinstance(d, dict):
                        for result in update_key(key, value, d):
                            yield result

list(update_key('Any level key', 'Any value', DICTIONARY))
Manoj Datt
  • 358
  • 1
  • 3
  • 10
1
from ndicts.ndicts import NestedDict

nd = NestedDict()
nd["myKey", "nestedDictKey1"] = 0
nd["myKey", "nestedDictKey2"] = 1
>>> nd
NestedDict({'myKey': {'nestedDictKey1': 0, 'nestedDictKey2': 1}})
>>> nd.to_dict()
{'myKey': {'nestedDictKey1': 0, 'nestedDictKey2': 1}}

To install ndicts pip install ndicts

edd313
  • 1,109
  • 7
  • 20
0
myDict["myKey"]["nestedDictKey2"] = anotherValue

myDict["myKey"] returns the nested dictionary to which we can add another key like we do for any dictionary :)

Example:

>>> d = {'myKey' : {'k1' : 'v1'}}
>>> d['myKey']['k2'] = 'v2'
>>> d
{'myKey': {'k2': 'v2', 'k1': 'v1'}}
slider
  • 12,810
  • 1
  • 26
  • 42
0

I wrote myself a function to tackle this issue

def updateDict2keys(myDict,mykey1,mykey2,myitems):
"""
updates a dictionary by appending values at given keys (generating key2 if not already existing)
input: dictionary, key1, key2 and items to append
output: dictionary orgnanized as {mykey1:{mykey2:myitems}}
"""
    myDict.setdefault(mykey1, {})[mykey2] = myitems
    return myDict
brodegon
  • 231
  • 2
  • 12