Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge values of same key, in list of dicts

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 dicts 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'}]
like image 955
DauleDK Avatar asked Jun 10 '15 12:06

DauleDK


People also ask

Can Dicts have same keys?

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.

How do I merge two Dicts together?

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

How do I merge a list of Dicts into a single dict?

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.

How do I merge dictionaries with common keys?

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.


2 Answers

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'}]
like image 78
thefourtheye Avatar answered Oct 15 '22 06:10

thefourtheye


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}]
like image 36
Lopabe Avatar answered Oct 15 '22 08:10

Lopabe