Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dictionary add values for the same keys

I have a list of dictionary:

[{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]

I want it to be:

[{'name':'Jay', 'value':'8'},{'name':'roc', 'value':'11'}]

I tried looping through but I am not able to find an example where I can do this. Any hint or idea will be appreciated.

like image 870
J. Doe Avatar asked May 25 '17 15:05

J. Doe


People also ask

Can we have multiple values for same key in dictionary python?

General Idea: In Python, if we want a dictionary to have multiple values for a single key, we need to store these values in their own container within the dictionary. To do so, we need to use a container as a value and add our multiple values to that container.

Can a dictionary have same keys with different values?

You can't. Keys have to be unique.


2 Answers

You can use a defaultdict:

lst = [{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]

1) sum values for each name:

from collections import defaultdict    
result = defaultdict(int)

for d in lst:
    result[d['name']] += int(d['value'])

2) convert the name-value pair to a dictionary within a list:

[{'name': name, 'value': value} for name, value in result.items()]
# [{'name': 'roc', 'value': 11}, {'name': 'Jay', 'value': 8}]

Or if you want the value as str type as commented by @Kevin:

[{'name': name, 'value': str(value)} for name, value in result.items()]
​# [{'name': 'roc', 'value': '11'}, {'name': 'Jay', 'value': '8'}]
like image 164
Psidom Avatar answered Sep 28 '22 11:09

Psidom


This is a good use case for itertools.groupby.

from itertools import groupby
from operator import itemgetter

orig = [{'name':'Jay', 'value':'1'},
        {'name':'roc', 'value':'9'},
        {'name':'Jay', 'value':'7'},
        {'name':'roc', 'value':'2'}]

get_name = itemgetter('name')
result = [{'name': name, 'value': str(sum(int(d['value']) for d in dicts))}
           for name, dicts in groupby(sorted(orig, key=get_name), key=get_name)]

Breaking it down:

  1. get_name is a function that given a dictionary, returns the value of its "name" key. I.e., get_name = lambda x: x['name'].

  2. sorted returns the list of dictionaries sorted by the value of the "name" key.

  3. groupby returns an iterator of (name, dicts) where dicts is a list (ok, generator) of the dicts that share name as the value of the "name" key. (Grouping only occurs for consecutive items with the same key value, hence the need to sort the list in the previous step.)

  4. The result is a list of new dictionaries using the given name and the sum of all the related "value" elements.

like image 31
chepner Avatar answered Sep 28 '22 11:09

chepner