0

I have the following list of dictionaries:

allChannelTraffic = [ { "Web" : 4, "android" : 3 }, { "Web" : 1 }, { "Web" : 1 }, { "Web" : 1 },]

I would like to know the easiest way to get an output like this from the above list:

[{'Web':7,'android':3}]  

Where I want to get the sum of the values of all the keys. I heard that using list comprehension in python, we can easily do operations. Can someone please tell me how to implement this using list comprehension?

Tony Mathew
  • 880
  • 1
  • 12
  • 35

5 Answers5

4

You can use Counter with sum:

from collections import Counter

allChannelTraffic = [{"Web": 4, "android": 3}, {"Web": 1}, {"Web": 1}, {"Web": 1}, ]

result = sum(map(Counter, allChannelTraffic), Counter())

print(result)

Output

Counter({'Web': 7, 'android': 3})
Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76
1

List comprehensions are not really useful here.

Generator expressions instead allows us to do the following:

allChannelTraffic = [ { "Web" : 4, "android" : 3 }, { "Web" : 1 }, { "Web" : 1 }, { "Web" : 1 },]
keys = set(k for d in allChannelTraffic for k in d.keys())
totals = {key: sum(d.get(key, 0) for d in allChannelTraffic) for key in keys}
print(totals)

# {'Web': 7, 'android': 3}

That last one {key: sum([...]) for key in keys} is a dictionary comprehension by the way.

And I could have used a set comprehension instead of the set() in line 2:

{k ... for k in d.keys()} == set(k ... for k in d.keys())

But I'd rather not do that, since the set() is much clearer for the reader.

In general though the Counter or Defaultdict approach for your problem might be more understandable for unexperienced pythonistas....

Sebastian Loehner
  • 1,302
  • 7
  • 5
0

You can use collections.defaultdict to sum up the values for each key

import collections
totals = collections.defaultdict(int)
for sub in allChannelTraffic:
    for key, value in sub.items():
        totals[key] += value

Output

>>> totals
defaultdict(<class 'int'>, {'android': 3, 'Web': 7})
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • Nice answer, but just cuz he wanted a list comprehension, here it'd be: `[totals[key] += value for key, value in sub.items() for sub in allChannelTraffic]` Not to steal your thunder, I just like one liners :) – Jab Nov 01 '18 at 11:39
  • 1
    @Jaba that would not work as the key would not exist and it would throw an error – Sina Khelil Nov 01 '18 at 11:40
  • It's a defaultdict though. I may be wrong.. – Jab Nov 01 '18 at 11:42
0

This isn't a list comprehension, but you can always use Counter.update() here:

from collections import Counter

allChannelTraffic = [ { "Web" : 4, "android" : 3 }, { "Web" : 1 }, { "Web" : 1 }, { "Web" : 1 }]

counts = Counter()
for d in allChannelTraffic:
    counts.update(d)

print(counts)
# Counter({'Web': 7, 'android': 3})

A non-library approach would look something like this:

allChannelTraffic = [ { "Web" : 4, "android" : 3 }, { "Web" : 1 }, { "Web" : 1 }, { "Web" : 1 }]

counts = {}
for d in allChannelTraffic:
    for k in d:
        counts[k] = counts.get(k, 0) + d[k]

print(counts)
# Counter({'Web': 7, 'android': 3})
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
0
allChannelTraffic = [ { "Web" :4,"android" : 3 }, { "Web" : 1 }, { "Web" : 1 },{ "Web" : 1 },] 
allChannelTraffic = [{"web": sum([item[1].get("Web",0) for item in enumerate(allChannelTraffic)]), "android":sum([item[1].get("android",0) for item in enumerate(allChannelTraffic)])}]
kelvo
  • 1
  • 3