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?
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}
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 })
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))
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
You could treat the nested dict as immutable:
myDict["myKey"] = dict(myDict["myKey"], **{ "nestedDictKey2" : anotherValue })
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'}}
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
Related
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?
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}
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 })
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))
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
You could treat the nested dict as immutable:
myDict["myKey"] = dict(myDict["myKey"], **{ "nestedDictKey2" : anotherValue })
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'}}
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
I have two dictionaries that may be formatted like the following:
d1 = { "root" : { "leaf" : [diff1, diff2] }}
d2 = { "root" : { "leaf": [diff3], "node": { "leaf" : [diff1] } } }
I would like to be able to combine them into such a result:
d3 = {'root': {'leaf': ['diff1', 'diff2', 'diff 3'], 'node': {'leaf': ['diff 1']}}}
The level of recursion is undefined for any given input, but every "leaf node" will be an array, which I would like to combine if one exists for a leaf node in each dictionary. NOTE: The keys are not actually "node" and "leaf", i simply used these keys to help illustrate the example.
This code seems to completely overwrite my arrays with the second one:
d3 = {**d1, **d2} yielding
result = {'root': {'leaf': ['diff 3'], 'node': {'leaf': ['diff 1']}}}
Untested, but something like this should work:
def dictmerge(d1, d2):
if d1 is None:
return d2
if d2 is None:
return d1
if isinstance(d1, list) and isinstance(d2, list):
return d1+d2
if isinstance(d1, dict) and isinstance(d2, dict):
return {k: dictmerge(d1.get(k), d2.get(k))
for k in set(d1.keys()) | set(d2.keys())}
raise ValueError, "inputs have incompatible structure"
You can do this with a recursive function. Note this will only merge lists, not tuples or any other kind of sequence:
def merge_dicts(d1, d2):
out_dict = {}
for key in (set(d1.keys()) | set(d2.keys())):
if key in d1 and key in d2:
if isinstance(d1[key], dict) and isinstance(d2[key], dict):
out_dict[key] = merge_dicts(d1[key], d2[key])
elif isinstance(d1[key], list) and isinstance(d2[key], list):
out_dict[key] = d1[key] + d2[key]
elif d1[key] == d2[key]:
out_dict[key] = d1[key]
else:
raise ValueError(
'Cannot merge conflicting values {} and {}'.format(
d1[key], d2[key]))
elif key in d1:
out_dict[key] = d1[key]
else:
out_dict[key] = d2[key]
return out_dict
d1 = { "root" : { "leaf" : ['diff1', 'diff2'] }}
d2 = { "root" : { "leaf": ['diff3'], "node": { "leaf" : ['diff1'] } } }
print(merge_dicts(d1, d2))
You haven't defined what to do if you call merge_dicts({'key': 'value'}, {'key': 'different_value'}). I have it raising a ValueError, since I would think you can't merge these two dicts (which value would you take?) but you can change that if you want to pick the value from one of the dicts as default, for example.
I have two dictionary like :
A = {
"Name": ["AAAAA"],
"designation": ["DDDDDDD"],
"doj": ["KKKKKK"],
"RRRRRRRR": ["JJJJJJ"]
}
B = {
{
u'IIIIII': u'200',
u'KKKKKK': u'1/1/2015',
u'JJJJJJ': u'legal',
u'HHHHHH': u'John'
}{
u'AAAAA': u'Stacie',
u'DDDDDDD': u'6/8/2014',
u'BBBB': u'2/9/1988',
u'CCCCCCC': u'legal'
}
}
I have to take the value of A and compare to key of B and if the name matches I should get the value of key from B and store. Something like
{
"Name": ["John"],
"designation": ["12/02/2016"],
"doj":["Manager"]
}
I am trying to loop both and then trying to append value to a dict item using the get method but could not achieve the goal.
for key,value in content.iteritems():
#print value
if isinstance(value, list):
vals.append(key)
for i in value:
ii=0
#while(ii<len(z)):
if (z.get(i)== 'true' ) :
vals.append(z.get(i))
This solution is considering the values of A and B provided in the question:
z = {}
for k, v in A.items():
av = B.get(v[0], None)
if av is not None:
z[k] = av
print(z)
# {'Name': ['John'], 'designation': ['12/02/2016'], 'doj': ['Manager']}
or, a one liner:
z = {k: B[v[0]] for k, v in A.items() if v[0] in B}
# {'Name': ['John'], 'designation': ['12/02/2016'], 'doj': ['Manager']}
How do i campare dictionaries that contain dictionaries ?
This will work in case the dictionaries contain simple values
# will show the keys with different values
d1_keys = set(dict1.keys())
d2_keys = set(dict2.keys())
intersect_keys = d1_keys.intersection(d2_keys)
modified = {}
for i in intersect_keys:
if dict1[i] != dict2[i] : modified.update({i : (dict1[i], dict2[i])})
but i have a dictionary like this:
{ 'medic1' : {'date' : '02/02/2015', 'no' : '123' }, 'medic2' : {'date' :'02/03/2015', 'no' : '456' }}
By recursion function for nested dictionary.
Get common keys from both dictionary by keys() and set operation.
Iterate common keys by for loop.
Check type of value of key is dict or not.
If value type is dict then call same function and pass values dictionary as arguments. and add result as key into modified dictionary.
If value type is not dict then add into modified dictionary.
code:
dict1 = {
'medic1' : {'date' : '02/02/2015', 'no' : '123' },
'medic2' : {'date' : '02/03/2015', 'no' : '456' },
'testkey1': 'testvalue1',
'testkey2': 'testvalue2',
'testkey3':{ "level2_1":"value2_1",
"level2_2":{
"level3_1": "value3_1_change",
"level3_2": "value3_2",
}
}
}
dict2 = {
'medic1' : {'date' : '02/02/2015', 'no' : '456' },
'medic2' : {'date' : '02/03/2015', 'no' : '456' },
'testkey1': 'testvalue1',
'testkey2': 'testvalue22',
'testkey3':{ "level2_1":"value2_1",
"level2_2":{
"level3_1": "value3_1",
"level3_2": "value3_2",
}
}
}
import copy
def compareDict(dict1, dict2):
d1_keys = dict1.keys()
d2_keys = dict2.keys()
intersect_keys = set(d1_keys).intersection(set(d2_keys))
modified = {}
for i in intersect_keys:
if dict1[i] != dict2[i] :
if isinstance(dict1[i], dict) and isinstance(dict1[i], dict):
modified[i]=compareDict(dict1[i], dict2[i])
else:
modified.update({i : (dict1[i], dict2[i])})
return copy.deepcopy(modified)
modified = compareDict(dict1, dict2)
import pprint
pprint.pprint(modified)
output:
vivek#vivek:~/Desktop/stackoverflow$ python 5.py
{'medic1': {'no': ('123', '456')},
'testkey2': ('testvalue2', 'testvalue22'),
'testkey3': {'level2_2': {'level3_1': ('value3_1_change', 'value3_1')}}}
As long as the keys are hashable (which a dict guarantees!-) it doesn't matter whether the values are or not -- code like:
common_keys = set(dict1).intersection(dict2)
(a simplified version of your first three lines), then
modified = {k: (dict1[k], dict2[k])
for k in common_keys if dict1[k] != dict2[k]}
(a simplified version of your last three lines) will work fine!
Python beginner here. I have a dictionary with a key and its value is an object (dict) who also has a key value pair. I want to add a key value pair to the 'child' object.
given:
{"foo" :
{"bar" : "bars value"}
}
I want to add:
{"foo" :
{"bar" : "bar value",
"baz" : "baz value"
}
}
This seems incredibly common but I can't seem to find a good way to do it.
somedict = {"foo" :
{"bar" : "bars value"}
}
somedict['foo']['baz'] = 'baz value'
When Python encounters somedict['foo']['baz'] it first looks-up the value of the bare name somedict. It finds it is a dict. Then it evaluates somedict['foo'] and finds it is another dict. Then it assigns to this dict a new key 'baz' with value `baz value'.
You can just do
mydict["foo"]["baz"] = "baz value"
as in
>>> mydict = {"foo" : {"bar" : "bars value"}}
>>> mydict["foo"]["baz"] = "baz value"
>>> mydict
{'foo': {'baz': 'baz value', 'bar': 'bars value'}}
This will work without knowing the key-value pairs inside dic:
>>> dic = {"foo" : {"bar" : "bars value"}}
...
>>> pairs = (("baz", "baz value"),)
for k,v in pairs:
for k1 in dic:
dic[k1][k]= v
>>> dic
{'foo': {'baz': 'baz value', 'bar': 'bars value'}}
Another Example:
>>> dic = {"foo" : {"bar" : "bars value"},"bar" : {"bar" : "bars value"} }
>>> pairs = (("baz", "baz value"),)
for k,v in pairs:
for k1 in dic:
dic[k1][k]= v
...
>>> dic
{'foo': {'baz': 'baz value', 'bar': 'bars value'},
'bar': {'baz': 'baz value', 'bar': 'bars value'}}
An alternative using update():
def updateChild(d, pk, pair):
d["pk"].update((pair,))
d is the whole dictionary, pk is the parent key, and pair is a tuple of the child key and the update data. This is useful if you have the pair already, as it seems you might in the question title.