简体   繁体   中英

How to merge multiple dictionaries by key

I want to get an union-like merged dict of multiple (3 or more) dictionaries.

What I have:

d1 = {'key1': 'x1', 'key2': 'y1', 'key4': 'z1'}
d2 = {'key1': 'x2', 'key2': 'y2', 'key5': 'z2'}
d3 = {'key1': 'x3', 'key3': 'y3', 'key4': 'z3'}

What I want to get:

d_merged = {
    'key1' : ('x1', 'x2', 'x3'),
    'key2' : ('y1', 'y2', None),
    'key3' : (None, None, 'y3'),
    'key4' : ('z1', None, 'z3'), 
    'key5' : (None, 'z2', None)
}

What is the most pythonic / efficient way to to this?

I've found an example for 2 dictionaries here , but is there a better way (eg: a comprehension) what can solve the missing key problem for some dictionaries here?

Is there a way to do the same merge for any number of input dictionaries?

Produce a union of all the keys, then iterate over that union to gather values:

result = {key: (d1.get(key), d2.get(key), d3.get(key))
          for key in d1.keys() | d2.keys() | d3.keys()}

In Python 3, dict.keys() gives you a dictionary view object , which acts like a set. You can create a union of all keys in all dictionaries with | on those objects.

In Python 2, use dict.viewkeys() instead.

Demo:

>>> d1 = {'key1': 'x1', 'key2': 'y1', 'key4': 'z1'}
>>> d2 = {'key1': 'x2', 'key2': 'y2', 'key5': 'z2'}
>>> d3 = {'key1': 'x3', 'key3': 'y3', 'key4': 'z3'}
>>> {key: (d1.get(key), d2.get(key), d3.get(key))
...  for key in d1.keys() | d2.keys() | d3.keys()}
{'key1': ('x1', 'x2', 'x3'), 'key5': (None, 'z2', None), 'key3': (None, None, 'y3'), 'key4': ('z1', None, 'z3'), 'key2': ('y1', 'y2', None)}
>>> from pprint import pprint
>>> pprint(_)
{'key1': ('x1', 'x2', 'x3'),
 'key2': ('y1', 'y2', None),
 'key3': (None, None, 'y3'),
 'key4': ('z1', None, 'z3'),
 'key5': (None, 'z2', None)}

For an arbitrary sequence of dictionaries, use set().union(*dictionaries) and a tuple() call on a generator expression:

dictionaries = (d1, d2, d3)  # or more
result = {key: tuple(d.get(key) for d in dictionaries)
          for key in set().union(*dictionaries)}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM