'List of lists of tuples, sum element-wise

I have a list of lists of tuples. Each inner list contains 3 tuples, of 2 elements each:

[
[(3, 5), (4, 5), (4, 5)],
[(7, 13), (9, 13), (10, 13)],
[(5, 7), (6, 7), (7, 7)]
]

I need to get a single list of 3 tuples, summing all these elements "vertically", like this:

(3, 5),  (4, 5),  (4, 5)
 +  +     +  +     +  +  
(7, 13), (9, 13), (10, 13)
 +  +     +  +     +  +  
(5, 7),  (6, 7),  (7, 7)
  ||       ||       ||
[(15, 25), (19, 25), (21, 25)]

so, for example, the second tuple in the result list is given by the sums of the second tuples in the initial list

(4+9+6, 5+13+7) = (19, 25)

I'm trying with list/tuple comprehensions, but I'm getting a little lost with this.



Solution 1:[1]

You could do this pretty easily with numpy. Use sum on axis 0.

import numpy as np

l = [
[(3, 5), (4, 5), (4, 5)],
[(7, 13), (9, 13), (10, 13)],
[(5, 7), (6, 7), (7, 7)]
]


[tuple(x) for x in np.sum(l,0)]

Output

[(15, 25), (19, 25), (21, 25)]

Solution 2:[2]

You can use zip and sum for something a little longer, but without the heavyweight dependency on numpy if you aren't already using it.

>>> [tuple(sum(v) for v in zip(*t)) for t in zip(*x)]
[(15, 25), (19, 25), (21, 25)]

The outer zip pairs the corresponding tuples together; the inner zip pairs corresponding elements of those tuples together for addition.

Solution 3:[3]

You could do this with pure python code.

lst = [
[(3, 5), (4, 5), (4, 5)],
[(7, 13), (9, 13), (10, 13)],
[(5, 7), (6, 7), (7, 7)]
]

lst2 = []
for a in range(len(lst[0])):
    l = []
    for i in range(len(lst)):
        l.append(lst[i][a])
    lst2.append(l)
output = []
for a in lst2:
    t = [0 for a in range(len(lst[0][0]))]
    for i in range(len(a)):
        for z in range(len(a[i])):
            t[z]+= a[i][z]
    output.append(tuple(t))
print(output)

if you change the list then its is works.

output

IN:
lst = [
[(3, 5), (4, 5), (4, 5)],
[(7, 13), (9, 13), (10, 13)],
[(5, 7), (6, 7), (7, 7)]
]

OUT:
[(15, 25), (19, 25), (21, 25)]


IN:
lst = [
[(3, 5,2), (4, 5,3), (4, 5,1)],
[(7, 13,1), (9, 13,3), (10, 13,3)],
[(5, 7,6), (6, 7,3), (7, 7,7)]
]


OUT:
[(15, 25, 9), (19, 25, 9), (21, 25, 11)]

Solution 4:[4]

data = [
    [(3, 5), (4, 5), (4, 5)],
    [(7, 13), (9, 13), (10, 13)],
    [(5, 7), (6, 7), (7, 7)]
]

result = [tuple(sum(x) for x in zip(*t)) for t in zip(*data)]

print(result)

This is a one-liner, I don't think you can get more pythonic than this.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Chris
Solution 2 chepner
Solution 3 Sharim Iqbal
Solution 4 Robin Thibaut