Categories
dictionary merge python

How to merge dicts, collecting values from matching keys?

122

I have multiple dicts (or sequences of key-value pairs) like this:

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

How can I efficiently get a result like this, as a new dict?

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

4

  • 4

    @Salil: Can we assume that each key is present in all dictionaries?

    May 10, 2011 at 6:55

  • possible duplicate of merging Python dictionaries

    – johnsyweb

    May 10, 2011 at 7:15

  • Hi Space_C0wb0y, yes, the keys are present in all dictionaries.

    – Salil

    May 10, 2011 at 7:42


  • It’s absolutely crucial to specify whether all dicts have same keys.

    – yugr

    Sep 1, 2018 at 17:27

60

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))

5

  • 3

    Just “for k in d1” would do I think.

    – Salil

    May 10, 2011 at 8:38

  • and d.get(k, None) in place of d[k]

    – tahir

    May 23, 2013 at 14:05

  • 1

    @tahir This would mean that dicts have non-matching keys so iterating over d1 is not correct (it may miss keys in other dicts).

    – yugr

    Sep 1, 2018 at 17:26

  • 1

    For python 3 users: d1.iterkeys() =d1.items()

    – Riley

    Sep 7, 2018 at 7:35

  • It still doesn’t work for me in Python3.x. I’ve tried this even if my values are not arrays, and it works. However, the values output will be arrays. stackoverflow.com/questions/54040858/…

    – Ric S

    Jan 8, 2019 at 21:18


60

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))

5

  • 3

    Just “for k in d1” would do I think.

    – Salil

    May 10, 2011 at 8:38

  • and d.get(k, None) in place of d[k]

    – tahir

    May 23, 2013 at 14:05

  • 1

    @tahir This would mean that dicts have non-matching keys so iterating over d1 is not correct (it may miss keys in other dicts).

    – yugr

    Sep 1, 2018 at 17:26

  • 1

    For python 3 users: d1.iterkeys() =d1.items()

    – Riley

    Sep 7, 2018 at 7:35

  • It still doesn’t work for me in Python3.x. I’ve tried this even if my values are not arrays, and it works. However, the values output will be arrays. stackoverflow.com/questions/54040858/…

    – Ric S

    Jan 8, 2019 at 21:18


5

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)}

14

  • 2

    Order of elements in values() is undefined so you may be merging values from unrelated keys.

    – yugr

    Sep 1, 2018 at 16:18

  • I just applied the changes so it can now capture your feedback

    Sep 3, 2018 at 15:09

  • I don’t think the change will fix the issue. You need to use sorted(d.items()) or sorted(d.keys()) to achieve predictable results.

    – yugr

    Sep 4, 2018 at 8:17

  • Can you give an example that prove it otherwise? dict2_sorted is a sorted dictionary in python !

    Sep 4, 2018 at 13:58

  • 1

    I did a small research on this. In recent versions of Python (3.6+) iteration order started to match insertion order (see e.g. here) which makes your code pass. But this is considered to be an implementation detail which shouldn’t be relied on. My second example (see here) reliably fails in onlinegdb which uses old Python 3.4. Other online interpreters use newer Pythons so issue can not be reproduced there.

    – yugr

    Sep 5, 2018 at 15:07