10

Possible Duplicate:
How to sum dict elements

I have a list of dictionaries as following:

[{'Name': 'A', 'amt':100},
 {'Name': 'B', 'amt':200},
 {'Name': 'A', 'amt':300},
 {'Name': 'C', 'amt':400},
 {'Name': 'C', 'amt':500},
 {'Name': 'A', 'amt':600}]

I want to sum amt for each name and get following result in list of dict:

 [{'Name':'A', 'amt':1000},
  {'Name':'B', 'amt':200},
  {'Name':'C', 'amt':900}]
Community
  • 1
  • 1
Mav
  • 171
  • 1
  • 1
  • 6
  • 2
    have you done anything (anything at all)? or is this another case of a "make my code" question? – juliomalegria Dec 21 '11 at 03:07
  • 1
    If it is a duplicate, it would be nice if you gave the link to the duplicate question rather than just marking it as a duplicate – Gabe Dec 04 '14 at 22:41

5 Answers5

19
from collections import defaultdict

c = defaultdict(int)
for d in list_of_dictionaries:
    c[d['Name']] += d['amt']

It produces c:

{'A': 1000, 'C': 900, 'B': 200}

To convert it to list of dictionaries:

[{'Name': name, 'amt': amt} for name, amt in c.items()]

Result:

[{'Name': 'A', 'amt': 1000}, {'Name': 'C', 'amt': 900}, {'Name': 'B', 'amt':200}]
jfs
  • 399,953
  • 195
  • 994
  • 1,670
7

Another possible solution, this time using itertools:

lst = [
{'Name': 'A', 'amt':100},
{'Name': 'B', 'amt':200},
{'Name': 'A', 'amt':300},
{'Name': 'C', 'amt':400},
{'Name': 'C', 'amt':500},
{'Name': 'A', 'amt':600}]

import itertools as it
keyfunc = lambda x: x['Name']

groups = it.groupby(sorted(lst, key=keyfunc), keyfunc)
[{'Name':k, 'amt':sum(x['amt'] for x in g)} for k, g in groups]
Óscar López
  • 232,561
  • 37
  • 312
  • 386
2
output_dict = {}
for i in dict_list:
    if i['Name'] in output_dict:
        output_dict[i['Name']] = i['amt']
    else:
        output_dict[i['Name']] += i['amt']

Will give you a dictionary where the keys are names and amounts are values. If you must have it as a list of dicts:

[{'Name':key, 'amt':value} for key, value in output_dict.items()]
dave
  • 12,406
  • 10
  • 42
  • 59
2

Example solution

I am not sure it is "beautiful/Pythonic enough", but it is surely short and works without additional modules:

def get_amt(name):
    return lambda x: x['amt'] if x['Name']==name else 0

names = sorted(set(map(lambda x: x['Name'], data)))
result = [{'Name':name,'amt':sum(map(get_amt(name), data))} for name in names]

Proof

Proof is here: http://codepad.org/L1gcTpVK

If you supply data as in the question, the result will be equal to this:

[{'Name': 'A', 'amt': 1000}, {'Name': 'B', 'amt': 200}, {'Name': 'C', 'amt': 900}]

which is exactly as requested :)

Tadeck
  • 132,510
  • 28
  • 152
  • 198
0

You can do it like this:

def sum(dict_list):
    result_list = []
    name_dict = {}
    for dict_item in dict_list:
        name = dict_item['Name']
        amt = dict_item['amt']
        if name_dict.has_key(name):
            pos = name_dict[name]
            result_list[pos] = {'Name':name, 'amt': (result_list[pos]['amt']+amt)}
        else:
            result_list.append(dict_item)
            name_dict[name] = len(result_list) - 1
    return result_list
Frank Fang
  • 1,069
  • 8
  • 5