Combining 2 dictionaries with common key - python

I have two dictionaries and need to combine the values of similar keys in them. Here's an example:
dict1 = {'key1':[value11,value12,value13] , 'key2':[value21,value22,value23]}
dict2 = {'key1':[value14,value15] , 'key2':[value24,value25]}
I used :
dict3 = {}
for key in (dict1.viewkeys() | dict2.keys()):
if key in dict1: dict3.setdefault(key, []).append(dict1[key])
if key in dict2: dict3.setdefault(key, []).append(dict2[key])
which gives me:
dict3 = {'key1':[[value11,value12,value13],[value14,value15]] , 'key2':[[value21,value22,value23],[value24,value25]]}
What I want is a simple one like:
Desired output :
dict3 = {'key1':[value11,value12,value13,value14,value15] , 'key2':[value21,value22,value23,value24,value25]}

All you need to do is to modify append to extend which will then add the elements of the list rather than adding the list itself. See the list docs for more details on the difference between append and extend.
dict1 = {'key1':['value11','value12','value13'] , 'key2':['value21','value22','value23']}
dict2 = {'key1':['value14','value15'] , 'key2':['value24','value25']}
dict3 = {}
for key in set().union(dict1, dict2):
if key in dict1: dict3.setdefault(key, []).extend(dict1[key])
if key in dict2: dict3.setdefault(key, []).extend(dict2[key])
print(dict3)
# {'key2': ['value21', 'value22', 'value23', 'value24', 'value25'], 'key1': ['value11', 'value12', 'value13', 'value14', 'value15']}
Alternatively you could use a collections.defaultdict with the default set to list as shown below.
from collections import defaultdict
dict3 = defaultdict(list)
for key in set().union(dict1, dict2):
for dic in [dict1, dict2]:
if key in dic:
dict3[key] += dic[key]

You can do it much simpler but if you want to use your code just change append to extend
dict1 = {'key1':['value11','value12','value13'] , 'key2':['value21','value22','value23']}
dict2 = {'key1':['value14','value15'] , 'key2':['value24','value25']}
dict3 = {}
for key in (dict1.viewkeys() | dict2.keys()):
if key in dict1: dict3.setdefault(key, []).extend(dict1[key])
if key in dict2: dict3.setdefault(key, []).extend(dict2[key])
print dict3
output:
{'key2': ['value21', 'value22', 'value23', 'value24', 'value25'], 'key1': ['value11', 'value12', 'value13', 'value14', 'value15']}
You can read this post about the difference ov append to extend

Here is a generic method on which you can pass as many dict as you want as parameter.
>>> def mix_dict(*args):
res = {}
for d in args:
if not isinstance(d, dict):
continue
for k, v in d.iteritems():
res.setdefault(k, [])
if isinstance(v, list):
res[k].extend(v)
else:
res[k].append(v)
return res
>>> dict1 = {'key1':['value11','value12','value13'] , 'key2':['value21','value22','value23']}
>>> dict2 = {'key1':['value14','value15'] , 'key2':['value24','value25']}
>>> dict3 = mix_dict(dict1, dict2)
>>> print dict3
... {'key1': ['value11', 'value12', 'value13', 'value14', 'value15'],
'key2': ['value21', 'value22', 'value23', 'value24', 'value25']}

Here is another way to do this.
You can support merging N dicts of lists into a single dict of lists with this function:
def mergeDoLs(*dicts):
def flatten(LoL):
return [e for l in LoL for e in l]
rtr={k:[] for k in set(flatten(d.keys() for d in dicts))}
for k, v in flatten(d.items() for d in dicts):
rtr[k].extend(v)
return rtr
To use:
>>> dict1 = {'key1':['value11','value12','value13'] , 'key2':['value21','value22','value23'], 'key3':[1]}
>>> dict2 = {'key1':['value14','value15'] , 'key2':['value24','value25']}
>>> dict3 = {'key3':[2]}
>>> mergeDoLs(dict1, dict2, dict3)
{'key3': [1, 2], 'key2': ['value21', 'value22', 'value23', 'value24', 'value25'], 'key1': ['value11', 'value12', 'value13', 'value14', 'value15']}

Use dict.update() to merge two dictionaries keys: dict1['key1'].update(dict2['key1'])

Related

Why key error is combining while combining List of dictionary with same keys

I have a list of dictionary
dictio =[{'key1':'value1'}, {'key1':'value2'}, {'key1':'value3'}, {'key2':'value4'}, {'key2':'value5'}]
My desired out
{key1:[value1, value2, value3], key2:[value4, value5]}
My code throwing key error
{ k:[d[k] for d in dictio ] for k in dictio[0] }
i got solution from stack
d = {
k: [d.get(k) for d in dictio ]
for k in set().union(*dictio )
}
In this case out is having none
{'k2': [None, None, None, 'v4', 'v5'], 'k1': ['v1', 'v2', 'v3', None, None]}
Try:
{ k:[d[k] for d in dicts if k in d] for k in set().union(*dicts) }
Your code throws, because some dicts don't have all keys (for example key1 in fourth dictionary). if k in d amends that alloing to continue only those, that have.
EDIT: you need to union your dicts as well, otherwise you won't get all keys, only those present in first dictionary.
If you can guarantee the specified order of list items, you can use itertools.groupby:
{k[0]: [d[k[0]] for d in g] for k, g in groupby(d, lambda x: tuple(x))}
Example:
from itertools import groupby
d = [{'key1':'value1'}, {'key1':'value2'}, {'key1':'value3'}, {'key2':'value4'}, {'key2':'value5'}]
print({k[0]: [d[k[0]] for d in g] for k, g in groupby(d, lambda x: tuple(x))})
# {'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']}
You iterate over the dictionaries with for d in dict, and each time you use d.get(k). If a dictionary does not contain that key, it returns None, hence these are the Nones in the list.
I suggest you use a defaultdict instead, like:
from collections import defaultdict
result = defaultdict(list)
for subd in mydicts:
for k, v in subd.items():
result[k].append(v)
If you want to get rid of the "default" behavior after constructing the dictionary, you can wrap the result in a new dictionary, like:
result = dict(result)
so for the given sample dictionary, this will yield:
>>> result
defaultdict(<class 'list'>, {'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']})
>>> dict(result)
{'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']}
The above will work if dictionaries have multiple keys, etc. Furthermore we only make one pass over the list of dictionaries.
Note: please do not name your variables after builtin functions/classes like dict, since now you overwrite the reference to the dict class.
Code from your original post need slight modification to get it working as intended
dictio =[{'key1':'value1'}, {'key1':'value2'}, {'key1':'value3'}, {'key2':'value4'}, {'key2':'value5'}]
d = {
k: [d.get(k) for d in dictio if d.get(k) is not None]
for k in set().union(*dictio )
}
print(d)
Output:
{'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']}
Note usage of is not None for checking, which according to PEP-8 is the preferred way.
Different way to print
super_dict = {}
for d in dictio:
for l, m in d.items():
super_dict.setdefault(l, []).append(m)
super_dict
{'key1': ['value1', 'value2', 'value3'], 'key2': ['value4', 'value5']}
with collection set
import collections
super_dict1 = collections.defaultdict(set)
for d in dictio:
for k, v in d.items():
super_dict1[k].add(v)
dict(super_dict1)
{'key1': {'value1', 'value2', 'value3'}, 'key2': {'value4', 'value5'}}
list comprehension
combined_key_set= {key for d in dictio for key in d}
su_di = {key : [d[key] for d in dictio if key in d] for key in combined_key_set}
su_di
{'key2': ['value4', 'value5'], 'key1': ['value1', 'value2', 'value3']}
comprehension
{key : [d[key] for d in dictio if key in d] for key in [key for d in dictio for key in d]}

How to return the values of dictionary key that has gained new values in a different dictionary

I have question a bit similar to:Replacing the value of a Python dictionary with the value of another dictionary that matches the other dictionaries key
However in my case I got two dictionaries
dict1 = {'foo' : ['val1' , 'val2' , 'val3'] , 'bar' : ['val4' , 'val5']}
dict2 = {'foo' : ['val2', 'val10', 'val11'] , 'bar' : ['val1' , 'val4']}
What I want to return is
dict3 = {'foo' : ['val10', 'val11'] , 'bar' : ['val1']}
and the opposite which is
dict4 = {'foo' : ['val1', 'val3'] , 'bar' : ['val5']}
where dict3 returns a dictionary of the values the keys 'foo' and 'bar' has gained in dict2 and the dict4 is a dictionary of the values the keys 'foo' and 'bar' has lost in dict2
One way I have tried solving this is to:
iterate over both dictionaries then
if key of dict1 == key of dict2
return the values of the key in dict1 and compare with the values in dict2
return the values that aren't in both
as a dictionary of the key and those values
This idea isn't working and obviously highly inefficient. I was hoping there is a more efficient working way to do this
Two dict comprehensions will do the trick:
dict3 = {k: [x for x in v if x not in dict1[k]] for k, v in dict2.items()}
print(dict3)
# {'foo': ['val10', 'val11'], 'bar': ['val1']}
dict4 = {k: [x for x in v if x not in dict2[k]] for k, v in dict1.items()}
print(dict4)
# {'foo': ['val1', 'val3'], 'bar': ['val5']}
The above two comprehensions basically filter out the values from key that don't exist in the other dictionary, which is done both ways.
You can also do this without dict comprehensions:
dict3 = {}
for k,v in dict2.items():
dict3[k] = [x for x in v if x not in dict1[k]]
print(dict3)
# {'foo': ['val10', 'val11'], 'bar': ['val1']}
dict4 = {}
for k,v in dict1.items():
dict4[k] = [x for x in v if x not in dict2[k]]
print(dict4)
# {'foo': ['val1', 'val3'], 'bar': ['val5']}

How do I combine two dictionaries based on their values?

I currently have two dictionaries containing nucleotide strings as the key and their counts as the value.
example:
dict1 = {GGA:64231, GAT: 66582}
dict2 = {TCC:64231, ATC: 66582}
I want to make a new dictionary that looks like this:
dict3 = {'GGA:TCC':64231, 'GAT:ATC':66582}
How can I do this?
Simply swap the key/value pairs in the dictionary to build your new one (assuming you have unique values, and your dictionaries all have matching values):
Python 3:
dict1 = {'GGA':64231, 'GAT': 66582}
dict1 = {v:k for k,v in dict1.items()} # {66582: 'GAT', 64231: 'GGA'}
dict2 = {'TCC':64231, 'ATC': 66582}
dict2 = {v:k for k,v in dict2.items()} # {66582: 'ATC', 64231: 'TCC'}
dict3 = {"{}:{}".format(dict1[k],dict2[k]):k for k in dict1} # {'GGA:TCC': 64231, 'GAT:ATC': 66582}
Python 2.7 use iteritems() instead of items()
The way I would do that is using list comprehension, which I believe is more pythonic:
dict1 = {GGA:64231, GAT: 66582}
dict2 = {TCC:64231, ATC: 66582}
new_dict = { x+":"+y:dict1[x] for x in dict1.keys() for y in dict2.keys() if dict1[x] == dict2[y]}
And this is the output:
{'GGA:TCC': 64231, 'GAT:ATC': 66582}
i think it would be smarter to map them with the key as the numbers for example since they are the defining factor.
a={i:[w] for w,i in dict1.items()}
b={i:w if i not in a else a[i]+[w] for w,i in dict2.items()}
output
{64231: ['GGA', 'TCC'], 66582: ['GAT', 'ATC']}
or in your case
a={i:[w] for w,i in dict1.items()}
b={i:w if i not in a else ":".join(a[i]+[w]) for w,i in dict2.items()}
output
{64231: 'GGA:TCC', 66582: 'GAT:ATC'}
What a fun little problem. My version doesn't search the dict, it assumes your dicts have perfect information and the values can be sorted by the number value.
dict1 = {"GGA": 64231, "GAT": 66582}
dict2 = {"TCC": 64231, "ATC": 66582}
dict3 = {
"%s:%s" % (k, l): v
for (k, v), (l, b) in zip(
sorted(dict1.items(), key=lambda x: x[1]),
sorted(dict2.items(), key=lambda x: x[1]),
)
}
print(dict3)
I'll say though #TheoretiCAL's answer is likely the best.
One way may be to try using defaultdict:
from collections import defaultdict
dict1 = {'GGA':64231, 'GAT': 66582}
dict2 = {'TCC':64231, 'ATC': 66582}
result_dict = defaultdict(list)
# read first dictionary and add value as key and key to list of values
for k, v in dict1.items(): result_dict[v].append(k)
# read other dictionary and add value as key and key to list of values
for k, v in dict2.items(): result_dict[v].append(k)
# change key to value in dicitonary
result_dict = {':'.join(v):k for k, v in result_dict.items()}
print(result_dict)
Output:
{'GAT:ATC': 66582, 'GGA:TCC': 64231}

convert list of keys to nested dictionary

I'm trying to figure out how to create, for example, a dictionary that looks like this: d[keys[0]][keys[1]][keys[2]] from a list like this : keys = ["key1", "key2", "key3"] ...
I've tried the following:
keys = ["key1", "key2", "key3"]
d = {}
d_ref= d
for key_num, key in enumerate(keys):
if key_num < len(keys)-1:
d[key] = {}
d_ref = d[key]
else:
d_ref[key] = []
print(d)
but it results in this:
{'key1': {}, 'key2': {'key3': []}}
I'm aiming for this output:
{'key1' : { 'key2' : { "key3" : [] } } }
Update
Thanks to wim for the answer that led me to my desired result:
keys = ["key1", "key2", "key3"]
d = []
for key in reversed(keys):
d = {key: d}
print(d)
Just a simple for-loop should do the trick
>>> d = {}
>>> for k in reversed(keys):
... d = {k: d}
...
>>> d
{'key1': {'key2': {'key3': {}}}}
(edit: OP changed the question after posting) Should you want a list as initial value, just change the first assignment:
>>> d = []
>>> for k in reversed(keys):
... d = {k: d}
...
>>> d
{'key1': {'key2': {'key3': []}}}
After an edit made by the OP, the solution is now a one-liner:
result = reduce(lambda obj, key: {key: obj}, reversed(keys), [])
# {'key1': {'key2': {'key3': []}}}
Or with some functional programming:
from functools import reduce
keys = ["key1", "key2", "key3"]
result = reduce((lambda obj, key: {key: obj}), reversed(keys), dict())
print(result)
# {'key1': {'key2': {'key3': {}}}}
I agree with #Ajax1234 that this problem has a recursive flavor to it but I think it can be done much simpler code than his solution:
keys = ["key1", "key2", "key3"]
def nest(keys, value):
key, *rest = keys
if rest:
value = nest(rest, value)
return {key: value}
print(nest(keys, []))
You can use recursion:
def get_dictionary(s, d):
if not s[1:]:
return {s[0]:d}
else:
if not d:
return get_dictionary(s[1:], {s[0]:[]})
else:
return get_dictionary(s[1:], {s[0]:d})
print(get_dictionary(["key1", "key2", "key3"][::-1], {}))
Output:
{'key1': {'key2': {'key3': []}}}

How to merge two nested dict in python?

I have two nested dictionary data. I want to merge them to create one dictionary in python.
Dictionary data :
dict1 = {'employee':{'dev1': 'Roy'}}
dict2 = {'employee':{'dev2': 'Biswas'}}
Now I trying to create a dictionary like bellow from them.Required Output
dict_output = {'employee':{
'dev1': 'Roy',
'dev2': 'Biswas'
}
}
my try:
import json
dict1 = {'employee':{'dev1': 'Roy'}}
dict2 = {'employee':{'dev2': 'Biswas'}}
dict1.update(dict2)
print(json.dumps(dict1, indent=2))
Output:
{
"employee": {
"dev2": "Biswas"
}
}
I am unable to merge both the dictionary.Need help to merge them
This code is to support slightly different meaning of "merge". Let's say we have a nested dictionary:
dict1 = {'employee':{'devs':{'python':{'dev1':'Roy'}}}}
dict2 = {'employee':{'devs':{'cpp':{'dev1':'Biswas'}}}}
In this case the simple loop solution returns:
{'employee': {'devs': {'cpp': {'dev1': 'Biswas'}}}}
While the "intuitive" answer should be:
{'employee': {'devs': {'python': {'dev1': 'Roy'}, 'cpp': {'dev1': 'Biswas'}}}}
This is just a simple example, the real example may be much more complex.
Below is my attempt for such a nested dictionary. It works for nested data using recursion. And it also has some restrictions. For example if dict1 and dict2 have the same value which is not dictionary, dict2 has priority. On the other hand if dict1 contains dictionary and dict2 contains value with the same key, the priority is upon dict1 and dict2 is ignored. Other restrictions will require code changes.
def merge_dict(dict1, dict2):
for key, val in dict1.items():
if type(val) == dict:
if key in dict2 and type(dict2[key] == dict):
merge_dict(dict1[key], dict2[key])
else:
if key in dict2:
dict1[key] = dict2[key]
for key, val in dict2.items():
if not key in dict1:
dict1[key] = val
return dict1
dict1 = merge_dict(dict1, dict2)
You can just update the inner dictionary.
>>> dict1 = {'employee':{'dev1': 'Roy'}}
>>> dict2 = {'employee':{'dev2': 'Biswas'}}
>>>
>>> for key in dict1:
... if key in dict2:
... dict1[key].update(dict2[key])
...
>>> dict1
{'employee': {'dev2': 'Biswas', 'dev1': 'Roy'}}
Here's a solution that should work even if both dictionaries have different keys, and you want to keep them all.
from collections import defaultdict
dict1 = {'employee': {'dev1': 'Roy'}, 'aKeyNotInDict2': {}}
dict2 = {'employee': {'dev2': 'Biswas'}, 'aKeyNotInDict1': {}}
merged_dict = defaultdict(dict)
merged_dict.update(dict1)
for key, nested_dict in dict2.items():
merged_dict[key].update(nested_dict)
print(dict(merged_dict))
Output:
{
'employee': {'dev2': 'Biswas', 'dev1': 'Roy'},
'aKeyNotInDict2': {},
'aKeyNotInDict1': {}
}
#use a dict comprehension. Adding {} in get() is to set a default return value if the key doesn't exist in dict1
{k:dict(dict1.get(k,{}).items() + v.items()) for k,v in dict2.items()}
Out[689]: {'employee': {'dev1': 'Roy', 'dev2': 'Biswas'}}
#Alternatively, a less readable way to merge the dicts using the dict constructor.
{k:dict(dict1.get(k,{}), **v) for k,v in dict2.items()}
Out[690]: {'employee': {'dev1': 'Roy', 'dev2': 'Biswas'}}
Maybe you can try naapc package as follows:
>>> from naapc import NDict
>>> dict1 = NDict({'employee':{'dev1': 'Roy'}})
>>> dict2 = {'employee':{'dev2': 'Biswas'}}
>>> dict1.update(dict2)
>>> print(dict1)
{
"employee": {
"dev1": "Roy",
"dev2": "Biswas"
}
}
In case you want a normal dict:
normal_dict = deepcopy(dict1.raw_dict)
To install:
pip install naapc
doc in: https://github.com/eiphy/naapc
def m3(a,b):
if not isinstance(a,dict) and not isinstance(b,dict):return b
for k in b:
if k in a :
a[k] = m3(a[k], b[k])
else: a[k] = b[k]
return a
d1 = {1:{"a":"A"}, 2:{"b":"B"}}
d2 = {2:{"c":"C"}, 3:{"d":"D"}}
d3 = {1:{"a":{1}}, 2:{"b":{2}}}
d4 = {2:{"c":{222}}, 3:{"d":{3}}}
d5 = {'employee':{'dev1': 'Roy'}}
d6 = {'employee':{'dev2': 'Biswas'}}
print(m3(d1,d2))
print(m3(d3,d4))
print(m3(d5,d6))
"""
Output :
{1: {'a': 'A'}, 2: {'b': 'B', 'c': 'C'}, 3: {'d': 'D'}}
{1: {'a': {1}}, 2: {'b': {2}, 'c': {222}}, 3: {'d': {3}}}
{'employee': {'dev1': 'Roy', 'dev2': 'Biswas'}}
"""
Explanation:
If a and b are not dictionaries, return b
For each key in b, if the key is in a, then merge the values of the key in a and b.
If the key is not in a, then add the key and value to a.
Return a.
But yes, The best and shortest way is this:
def m4(a,b):
for k in a:
a.get(k).update(b.get(k, {}))
return a
Explanation:
The function m4 takes two dictionaries as input.
The function iterates through the first dictionary
and updates the values of the first dictionary with
the values of the second dictionary.
The function returns the first dictionary.
[key1 == key2 and dict1.get(key1).update(dict2.get(key2))
for key1, key2 in zip(dict1, dict2)]
print dict1

Categories

Resources