How to merge multiple dicts with same key or different key?

I have multiple dicts/key-value pairs like this:

d1 = {key1: x1, key2: y1}  
d2 = {key1: x2, key2: y2}  

I want the result to be a new dict (in most efficient way, if possible):

d = {key1: (x1, x2), key2: (y1, y2)}  

Actually, I want result d to be:

d = {key1: (x1.x1attrib, x2.x2attrib), key2: (y1.y1attrib, y2.y2attrib)}  

If somebody shows me how to get the first result, I can figure out the rest.


Solution 1:

Here's a general solution that will handle an arbitrary amount of dictionaries, with cases when keys are in only some of the dictionaries:

from collections import defaultdict

d1 = {1: 2, 3: 4}
d2 = {1: 6, 3: 7}

dd = defaultdict(list)

for d in (d1, d2): # you can list as many input dicts as you want here
    for key, value in d.items():
        dd[key].append(value)

print(dd)

Shows:

defaultdict(<type 'list'>, {1: [2, 6], 3: [4, 7]})

Also, to get your .attrib, just change append(value) to append(value.attrib)

Solution 2:

assuming all keys are always present in all dicts:

ds = [d1, d2]
d = {}
for k in d1.iterkeys():
    d[k] = tuple(d[k] for d in ds)

Note: In Python 3.x use below code:

ds = [d1, d2]
d = {}
for k in d1.keys():
  d[k] = tuple(d[k] for d in ds)

and if the dic contain numpy arrays:

ds = [d1, d2]
d = {}
for k in d1.keys():
  d[k] = np.concatenate(list(d[k] for d in ds))

Solution 3:

Here is one approach you can use which would work even if both dictonaries don't have same keys:

d1 = {'a':'test','b':'btest','d':'dreg'}
d2 = {'a':'cool','b':'main','c':'clear'}

d = {}

for key in set(d1.keys() + d2.keys()):
    try:
        d.setdefault(key,[]).append(d1[key])        
    except KeyError:
        pass

    try:
        d.setdefault(key,[]).append(d2[key])          
    except KeyError:
        pass

print d

This would generate below input:

{'a': ['test', 'cool'], 'c': ['clear'], 'b': ['btest', 'main'], 'd': ['dreg']}

Solution 4:

dict1 = {'m': 2, 'n': 4}
dict2 = {'n': 3, 'm': 1}

Making sure that the keys are in the same order:

dict2_sorted = {i:dict2[i] for i in dict1.keys()}

keys = dict1.keys()
values = zip(dict1.values(), dict2_sorted.values())
dictionary = dict(zip(keys, values))

gives:

{'m': (2, 1), 'n': (4, 3)}

Solution 5:

If you only have d1 and d2,

from collections import defaultdict

d = defaultdict(list)
for a, b in d1.items() + d2.items():
    d[a].append(b)