Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining 2 dictionaries with common key

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]}
like image 919
Hypothetical Ninja Avatar asked Aug 20 '14 13:08

Hypothetical Ninja


People also ask

How do you combine two dictionary values for common keys?

Using Counter The Counter function from the Collections module can be directly applied to merge the two dictionaries which preserves the keys. And in turn adds the values at the matching keys.

How do I merge two dictionaries in a single expression?

Using | in Python 3.9 In the latest update of python now we can use “|” operator to merge two dictionaries. It is a very convenient method to merge dictionaries.


3 Answers

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]
like image 135
Ffisegydd Avatar answered Oct 19 '22 05:10

Ffisegydd


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

like image 38
Kobi K Avatar answered Oct 19 '22 06:10

Kobi K


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']}
like image 34
Quentin THEURET Avatar answered Oct 19 '22 07:10

Quentin THEURET