231

How can I turn a list of dicts like [{'a':1}, {'b':2}, {'c':1}, {'d':2}], into a single dict like {'a':1, 'b':2, 'c':1, 'd':2}?


Answers here will overwrite keys that match between two of the input dicts, because a dict cannot have duplicate keys. If you want to collect multiple values from matching keys, see How to merge dicts, collecting values from matching keys?.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
killown
  • 4,497
  • 3
  • 25
  • 29
  • 3
    There really should be a one liner for this considering how often it comes up. Is there a reason why {**d for d in d_list} isn't supported? – markemus Jan 16 '20 at 01:00
  • 1
    @markemus being able to use star-unpacking in the first clause of a comprehension would quickly lead to chaos. For just one example: should `[*a for a in (range(i) for i in range(10))]` flatten the output or not? A feature like this would take a LOT of careful design work. Also, for dict comprehensions specifically, the `:` is kind of needed in the syntax, or else how do you know it isn't a set comprehension instead? – Karl Knechtel Aug 31 '22 at 01:20
  • @markemus See [Unpacking generalizations](https://stackoverflow.com/q/41251729/674039) about that. – wim Nov 29 '22 at 17:48
  • @KarlKnechtel I'm not convinced on those syntactical points. The first example _should_ flatten the output, because not flattening it would be written as just `[range(i) for i in range(10)]`. A set union/unpack would look like `{*s for s in ss}` and dict merge/unpack would look like `{**d for d in ds}`. So, the * vs ** is enough - no `:` is needed. – wim Nov 29 '22 at 17:50
  • " The first example should flatten the output," Okay, now have fun writing the parser logic for that, and making it not go "well, each `*a` produces a list clearly, and then we have a list comprehension of those". – Karl Knechtel Nov 30 '22 at 06:00

12 Answers12

292

This works for dictionaries of any length:

>>> result = {}
>>> for d in L:
...    result.update(d)
... 
>>> result
{'a':1,'c':1,'b':2,'d':2}

As a comprehension:

# Python >= 2.7
{k: v for d in L for k, v in d.items()}

# Python < 2.7
dict(pair for d in L for pair in d.items())
wim
  • 338,267
  • 99
  • 616
  • 750
179

In case of Python 3.3+, there is a ChainMap collection:

>>> from collections import ChainMap
>>> a = [{'a':1},{'b':2},{'c':1},{'d':2}]
>>> dict(ChainMap(*a))
{'b': 2, 'c': 1, 'a': 1, 'd': 2}

Also see:

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
23

Little improvement for @dietbuddha answer with dictionary unpacking from PEP 448, for me, it`s more readable this way, also, it is faster as well:

from functools import reduce
result_dict = reduce(lambda a, b: {**a, **b}, list_of_dicts)

But keep in mind, this works only with Python 3.5+ versions.

Insomniac631
  • 1,018
  • 12
  • 20
16

This is similar to @delnan but offers the option to modify the k/v (key/value) items and I believe is more readable:

new_dict = {k:v for list_item in list_of_dicts for (k,v) in list_item.items()}

for instance, replace k/v elems as follows:

new_dict = {str(k).replace(" ","_"):v for list_item in list_of_dicts for (k,v) in list_item.items()}

unpacks the k,v tuple from the dictionary .items() generator after pulling the dict object out of the list

Schalton
  • 2,867
  • 2
  • 32
  • 44
12

For flat dictionaries you can do this:

from functools import reduce
reduce(lambda a, b: dict(a, **b), list_of_dicts)
SiHa
  • 7,830
  • 13
  • 34
  • 43
dietbuddha
  • 8,556
  • 1
  • 30
  • 34
5

You can use join function from funcy library:

from funcy import join
join(list_of_dicts)
Suor
  • 2,845
  • 1
  • 22
  • 28
4
>>> L=[{'a': 1}, {'b': 2}, {'c': 1}, {'d': 2}]    
>>> dict(i.items()[0] for i in L)
{'a': 1, 'c': 1, 'b': 2, 'd': 2}

Note: the order of 'b' and 'c' doesn't match your output because dicts are unordered

if the dicts can have more than one key/value

>>> dict(j for i in L for j in i.items())
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
3

If you don't need the singleton dicts anymore:

>>> L = [{'a':1}, {'b':2}, {'c':1}, {'d':2}]
>>> dict(map(dict.popitem, L))
{'a': 1, 'b': 2, 'c': 1, 'd': 2}
no comment
  • 6,381
  • 4
  • 12
  • 30
2
dict1.update( dict2 )

This is asymmetrical because you need to choose what to do with duplicate keys; in this case, dict2 will overwrite dict1. Exchange them for the other way.

EDIT: Ah, sorry, didn't see that.

It is possible to do this in a single expression:

>>> from itertools import chain
>>> dict( chain( *map( dict.items, theDicts ) ) )
{'a': 1, 'c': 1, 'b': 2, 'd': 2}

No credit to me for this last!

However, I'd argue that it might be more Pythonic (explicit > implicit, flat > nested ) to do this with a simple for loop. YMMV.

Katriel
  • 120,462
  • 19
  • 136
  • 170
1

this way worked for me:

object = [{'a':1}, {'b':2}, {'c':1}, {'d':2}]
object = {k: v for dct in object for k, v in dct.items()}

printing object:

object = {'a':1,'b':2,'c':1,'d':2}

thanks Axes

Shokouh Dareshiri
  • 826
  • 1
  • 12
  • 24
0
>>> dictlist = [{'a':1},{'b':2},{'c':1},{'d':2, 'e':3}]
>>> dict(kv for d in dictlist for kv in d.iteritems())
{'a': 1, 'c': 1, 'b': 2, 'e': 3, 'd': 2}
>>>

Note I added a second key/value pair to the last dictionary to show it works with multiple entries. Also keys from dicts later in the list will overwrite the same key from an earlier dict.

Dave Kirby
  • 25,806
  • 5
  • 67
  • 84
0

Using reduce and | seems to be slightly faster than the list comprehension in the accepted answer.

In [1]: %timeit reduce(lambda d1, d2: d1 | d2, L)
428 ns ± 5.41 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

In [2]: %timeit {k: v for d in L for k, v in d.items()}
476 ns ± 15.4 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

In [3]: reduce(lambda d1, d2: d1 | d2, L) == {k: v for d in L for k, v in d.items()}
Out[3]: True
ndrwnaguib
  • 5,623
  • 3
  • 28
  • 51