Stagg
Stagg

Reputation: 309

Sum the values that have the same key in a dictionary

I have this list of dictionaries:

[{'Total Incidents': '1', 'CrimeTime': '19'}, 
 {'Total Incidents': '1', 'CrimeTime': '19'}, 
 {'Total Incidents': '1', 'CrimeTime': '19'}, 
 {'Total Incidents': '1', 'CrimeTime': '20'}, 
 {'Total Incidents': '1', 'CrimeTime': '20'},
 {'Total Incidents': '1', 'CrimeTime': '21'},
 {'Total Incidents': '1', 'CrimeTime': '21'}]

I need to convert the value of 'Total Incidents' to int, and sum them up, for each incident that occured in the same hour (the minutes and seconds are irrelevant). The output should be something like this:

[{'Total Incidents': 3, 'CrimeTime': '19'},
 {'Total Incidents': 2, 'CrimeTime': '20'},
 {'Total Incidents': 2, 'CrimeTime': '21'}]

I have used this method:

 [{ 'CrimeTime':       g[0], 
    'Total Incidents': sum(map(lambda x: int(x['Total Incidents']), g[1])) } 
  for g in itertools.groupby(mydata, lambda x: x['CrimeTime']) ]

But unfortunately, sometimes it repeats 'CrimeTime' so I get two dictionaries with the same 'CrimeTime', instead of only one with the summed incidents. The original list is a lot bigger, I just used a short version to explain myself better.

Feel free to ask if you don't understand my question so that I can explain myself a bit better.

Upvotes: 1

Views: 965

Answers (2)

user2390182
user2390182

Reputation: 73460

In most contexts (as in yours), itertools.groupby works best if the data is sorted by the grouping key because it only groups adjacent elements:

key = lambda x: x['CrimeTime']
[
    {'CrimeTime': k, 'Total Incidents': sum(int(x['Total Incidents']) for x in g)} 
    for k, g in itertools.groupby(sorted(mydata, key=key), key=key)
]

Using the generator expression instead of the map-lambda is mostly a matter of taste, but, at least in Python 2, saves you some resources by not building an intermediate list.

Upvotes: 3

A.H
A.H

Reputation: 1025

This should work : (too late ;) )

 [
   {'CrimeTime': g[0], 'Total Incidents': sum(map(lambda x: int(x['Total Incidents']), g[1]))} 
      for g in 
        itertools.groupby(
          sorted(data,key=lambda x:x.values()[0]), lambda x: x['CrimeTime'])
]

Upvotes: 1

Related Questions