how to combine multiple dictionaries from list?

Question:

I have a list of dictionaries like this one:

 my_dict =  [{'year-0': '2022', 'dividend-0': ''},
 {'year-1': '2021', 'dividend-1': '52.37'},
 {'year-2': '2020', 'dividend-2': '44.57'},
 {'year-3': '2019', 'dividend-3': '35.00'},
 {'year-4': '2018', 'dividend-4': '24.00'},
 {'year-5': '2017', 'dividend-5': '23.94'}]

How I can combine these dictionaries into one dictionary like that ?:

{'year-0': '2022',
 'dividend-0': '',
 'year-1': '2021',
 'dividend-1': '52.37',
 'year-2': '2020',
 'dividend-2': '44.57',
 'year-3': '2019',
 'dividend-3': '35.00',
 'year-4': '2018',
 'dividend-4': '24.00',
 'year-5': '2017',
 'dividend-5': '23.94'}

I can do it using a simple loop, but maybe there is a more elegant way ?

x=dict()
for d in my_dict:
    x.update(d)
Asked By: krokodilko

||

Answers:

You can use dictionary comprehension:

new_dict ={x:y for d in my_dict for x,y in d.items()}

Which gives your wanted result from your data.

Answered By: user19077881

The output data structure can probably be optimized into a dictionary of strings or a dictionary of numbers, like so:

dct1 = {tuple(item.values())[0] : tuple(item.values())[1] for item in my_dict}
print(dct1)
# {'2022': '', '2021': '52.37', '2020': '44.57', '2019': '35.00', '2018': '24.00', '2017': '23.94'}

dct2 = {}
for item in my_dict:
    vals = tuple(item.values())
    k = int(vals[0])
    try:
        v = float(vals[1])
    except:
        v = None
    dct2[k] = v

print(dct2)
# {2022: None, 2021: 52.37, 2020: 44.57, 2019: 35.0, 2018: 24.0, 2017: 23.94}

Although this is not exactly what you asked for, this data structure may be better in that it is not as repetitive. Note that the first example uses dictionary comprehension, and the second example uses a simple loop for readability.

Answered By: Timur Shtatland

A short investigation delivers (on my PC, Python 3.9):

>>> timeit.timeit(lambda: {x:y for d in my_dict for x,y in d.items()}, number=100) 
0.00012549999519251287

>>> def build(my_dict):
...     x=dict()
...     for i in my_dict:
...         x.update(i)
...     return x
... 
>>> timeit.timeit(lambda: build(my_dict), number=100)
7.940000796224922e-05

>>> timeit.timeit(lambda: functools.reduce(lambda i,ii: i.update(ii) or i ,my_dict), number=100)
6.53000024612993e-05

The conclusion for my setup is that the double comprehension is not the better solution. Original code is quicker and better readable. functools.reduce() as already proposed by Barma is the quickest solution but here it modifies original list/dicts.

Answered By: B.R.
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.