Reputation: 67
I have a list of tuples, for example:
(1,3)
(1,2)
(1,7)
(2,4)
(2,10)
(3,8)
I need to be able to sum up the second values based upon what the first value is, getting this result for the example list:
(1,12)
(2,14)
(3,8)
This question is very similar in nature to this one, however, my solution may not use any imports or for loops, and all answers to that question use one or the other. It's supposed to rely on list and set comprehension.
Upvotes: 3
Views: 3674
Reputation: 8362
I'd use a defaultdict
from collections import defaultdict
x = [(1,3), (1, 2), (1, 7), (2, 4), (2, 10), (3, 8)]
d = defaultdict(int)
for k, v in x:
d[k] += v
print(list(d.items()))
if you need a one-liner (lambda inline function) using itertools
from itertools import groupby
myfunc = lambda tu : [(k, sum(v2[1] for v2 in v)) for k, v in groupby(tu, lambda x: x[0])])
print(myfunc(x))
Upvotes: 0
Reputation: 15310
This is pretty straightforward, but it's definitely O(n**2), so keep your input data small:
data = (
(1,3),
(1,2),
(1,7),
(2,4),
(2,10),
(3,8),
)
d = { k:v for k,v in data }
d2 = [(t1,sum( v for k,v in data if k == t1 )) for t1 in d.keys() ]
print(d2)
Output is
[(1, 12), (2, 14), (3, 8)]
Upvotes: 0
Reputation: 180411
If you are using python2, you can use map to behave like izip_longest
and get the index of where the groups end:
def sums(l):
st = set()
inds = [st.add(a) or ind for ind, (a, b) in enumerate(l) if a not in st]
return [(l[i][0], sum(sub[1] for sub in l[i:j])) for i, j in map(None, inds, inds[1:])]
Output:
In [10]: print(sums(l))
[(1, 12), (2, 14), (3, 8)]
for python 2 or 3 you can just use enumerate and check the index:
def sums(l):
st = set()
inds = [st.add(a) or ind for ind, (a, b) in enumerate(l) if a not in st]
return [(l[j][0], sum(sub[1] for sub in (l[j:inds[i]] if i < len(inds) else l[inds[-1]:])))
for i, j in enumerate(inds, 1)]
same output:
In [12]: print(sums(l))
[(1, 12), (2, 14), (3, 8)]
Upvotes: 0
Reputation: 2509
If you can use dictionaries the following should work
x = [(1,3), (1, 2), (1, 7), (2, 4), (2, 10), (3, 8)]
d = {}
[d.__setitem__(first, d.get(first, 0) + second) for first, second in x]
print(list(d.items()))
Upvotes: 0
Reputation: 113978
my_set = {x[0] for x in my_tuples}
my_sums = [(i,sum(x[1] for x in my_tuples if x[0] == i)) for i in my_set]
I guess. ... those requirements are not very good for this problem (this solution will be slow ...)
Upvotes: 3