drbunsen
drbunsen

Reputation: 10689

zip function help with tuples

I am hoping someone can help me with a problem I'm stuck with. I have a large number of tuples (>500) that look like this:

(2,1,3,6)  
(1,2,5,5)  
(3,0,1,6)  
(10,1,1,4)  
(0,3,3,0)  

A snippet of my code reads:

sum1 = (A,B,C,D) # creates a tuple of sums of (A,B,C,D)  
mysum = map(sum, zip(A, B, C, D))
print(mysum)

I realize the above code is not correct. I am trying to find a way to add all the values A together, all the values of B together, all the values of C together, and all the values of D together using the zip function. For example, I would like to print something that looks like this:

Asum = 16  
Bsum = 7  
Csum = 13  
Dsum = 21  

Can anyone help please? Thanks very much for your time.

Upvotes: 8

Views: 48594

Answers (5)

ninjagecko
ninjagecko

Reputation: 91094

>>> zip((1,2,3),(10,20,30),(100,200,300))
[(1, 10, 100), (2, 20, 200), (3, 30, 300)]

>>> [sum(x) for x in zip((1,2,3),(10,20,30),(100,200,300))]
[111, 222, 333]

To do this with an arbitrarily large set of tuples:

>>> myTuples = [(1,2,3), (10,20,30), (100,200,300)]
>>> [sum(x) for x in zip(*myTuples)]
[111, 222, 333]

sidenote: in python3, note that zip returns a lazy iterable, which you can always explicitly turn into a list like any other kind of iterable: list(zip(...))

(thanks to Seganku for catching mistake in examples in an edit which was thrice rejected by other editors)

Upvotes: 17

Carl F.
Carl F.

Reputation: 7056

It your sets are all the same size and you are working in C Python, you should consider using numpy. You can do this in numpy like so:

In [5]: sets = ((2,1,3,6),
   ...:         (1,2,5,5),
   ...:         (3,0,1,6),
   ...:         (10,1,1,4),
   ...:         (0,3,3,0)  )*100

In [6]: import numpy as np

In [7]: A = np.array(sets)

In [8]: np.sum(A, axis=0)
Out[8]: array([1600,  700, 1300, 2100])

Numpy converts your values to an array and works with them efficiently using optimized LAPACK functions.

To compare performance, I profiled under two sets of assumptions. In the first, I assume that your data is stored such that importing into a Numpy array is efficient, so I didn't include the time necessary to convert sets to an array. I compared the performance of np.sum to [sum(x) for x in zip(*sets)]. Here are the timeit results for each case:

Excluding numpy Array Conversion: 0.0735958760122
Including numpy Array Conversion: 17.1435046214
Plain old zip: 0.660146750495

The conclusion is that numpy is faster if your input data can easily be imported with numpy.

Upvotes: 2

Vasil
Vasil

Reputation: 38116

tuples  = [(2,1,3,6), (1,2,5,5),  (3,0,1,6), (10,1,1,4), (0,3,3,0)]
s = [sum(tup) for tup in zip(*tuples)]
Asum, Bsum, Csum, Dsum = s

Upvotes: 0

Felix Kling
Felix Kling

Reputation: 816404

If you have all that tuples in a list, then you could use reduce():

>>> list(reduce(lambda x,y: (i+j for i,j in zip(x,y)), tuples, [0]*4))
[16, 7, 13, 21]

Upvotes: 0

user79758
user79758

Reputation:

map(sum, zip(a, b, c, d, e))

The first call, to zip, inverts the lists - makes a list of all first elements, all second elements, etc.

The second call, map, calls its first argument sum on its second argument, those lists, returning a list of the results of sum - which happens to be the sums.

Upvotes: 4

Related Questions