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