I am relatively new to python 2.7, and can't figure out the following despite searching extensively on StackOverflow:
I have a list
of dict
s I wan't to combine, when key is the same, and add specific values (in the example 'price'
).
Input:
[{'id1': 'a', 'price': '2', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}, {'id1': 'a', 'price': '2', 'color': 'green'}]
Expected:
[{'id1': 'a', 'price': '4', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}]
In this article, we will find out whether a dictionary has duplicate keys or not in Python. The straight answer is NO. You can not have duplicate keys in a dictionary in Python.
Python 3.9 has introduced the merge operator (|) in the dict class. Using the merge operator, we can combine dictionaries in a single line of code. We can also merge the dictionaries in-place by using the update operator (|=).
To merge multiple dictionaries, the most Pythonic way is to use dictionary comprehension {k:v for x in l for k,v in x. items()} to first iterate over all dictionaries in the list l and then iterate over all (key, value) pairs in each dictionary.
Merging two dictionaries having common keys using **kwargs Keys that are common in both d1 and d2 will contain values from d2. If d3={**d2,**d1} -Keys that are common in both d1 and d2 will contain values from d1.
Same idea as your question before the edit.
>>> data = [{'id1': 'a', 'price': '2', 'color': 'green'},
... {'id1': 'b', 'price': '5', 'color': 'red'},
... {'id1': 'a', 'price': '2', 'color': 'green'}]
Construct a temporary dictionary and accumulate values in it
>>> temp = {}
>>> for d in data:
... if d['id1'] not in temp:
... temp[d['id1']] = {}
... temp_d = temp[d['id1']]
... temp_d['price'] = temp_d.get('price', 0) + int(d['price'])
... temp_d.setdefault('colors', set()).add(d['color'])
...
>>> temp
{'a': {'colors': {'green'}, 'price': 4}, 'b': {'colors': {'red'}, 'price': 5}}
Then using list comprehension and dictionary comprehension, reconstruct the list of dictionaries.
>>> [{'id1': k, 'price': v['price'], 'colors': v['colors']} for k, v in temp.items()]
[{'id1': 'a', 'colors': {'green'}, 'price': 4}, {'id1': 'b', 'colors': {'red'}, 'price': 5}]
>>> data = [{'id1': 'a', 'price': '2'}, {'id1': 'b', 'price': '5'},
... {'id1': 'a', 'price': '2'}]
Create a temporary dictionary where we can accummulate the sum of prices against their ids,
>>> temp = {}
>>> for d in data:
... temp[d['id1']] = temp.get(d['id1'], 0) + int(d['price'])
...
>>> temp
{'a': 4, 'b': 5}
Here we try to get the value of d['id1']
from temp
and if it is not found, 0 will be returned. We then add the price
from the current dictionary and store the result back in the temp
against the current id1.
Then reconstruct the list of dictionaries, with list comprehension and dictionary comprehension, like this
>>> [{'id1': k, 'price': temp[k]} for k in temp]
[{'price': 4, 'id1': 'a'}, {'price': 5, 'id1': 'b'}]
I've managed to compact the code like this:
import itertools as it
from operator import itemgetter
grupos = it.groupby(sorted(data, key=itemgetter('id1')), key=itemgetter('id1'))
res = [{'id1': v, 'price': sum(int(dicc['price']) for dicc in diccs) } for v, diccs in
grupos]
print(res)
the output is:
[{'id1': 'a', 'price': 4}, {'id1': 'b', 'price': 25}, {'id1': 'c', 'price': 2}, {'id1': 'd', 'price': 1}, {'id1': 'e', 'price': 20}]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With