# sum of products for multiple lists in python

### Question

Trying to imitate Excel's SUMPRODUCT function:

``````SUMPRODUCT(v1, v2, ..., vN) =
v1*v2*...*vN + v1*v2*...*vN + ... + v1[n]*v2[n]*...*vN[n]
``````

where n is the number of elements in each vector.

This is similar to dot product, but for multiple vectors. I read the very detailed discussion of the regular dot product, but I don't know how to cleanly extend it to multiple vectors. For reference, I'm copying the optimized code proposed there, which I ported (trivially) to Python 3. BTW, for dot product, the last approach still wins in P3K.

``````def d0(v1,v2):
"""
d0 is Nominal approach:
"""
out = 0
for k in range(len(v1)):
out += v1[k] * v2[k]
return out

def d1(v1,v2):
"""
d1 uses a map
"""
return sum(map(mul,v1,v2))

def d3(v1,v2):
"""
d3 uses a starmap (itertools) to apply the mul operator on an zipped (v1,v2)
"""
return sum(starmap(mul,zip(v1,v2)))
``````
1
9
6/28/2018 12:56:09 AM

``````import operator

def sumproduct(*lists):
return sum(reduce(operator.mul, data) for data in zip(*lists))
``````

for python 3

``````import operator
import functools

def sumproduct(*lists):
return sum(functools.reduce(operator.mul, data) for data in zip(*lists))
``````
19
10/3/2010 9:36:15 AM

What about good old list comprehensions? (As mentioned by @Turksarama this only works for two lists)

``````sum([x * y for x, y in zip(*lists)])
``````

Testing in Python 3.6:

``````In : import random

In : x = [random.randint(0,100) for _ in range(100)]

In : y = [random.randint(0,100) for _ in range(100)]

In : lists = x, y
``````

Using list comprehensions

``````In : %timeit(sum([x * y for x, y in zip(*lists)]))
8.73 µs ± 24.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
``````

Note that "tuple" comprehensions are slower

``````In : %timeit(sum(x * y for x, y in zip(*lists)))
10.5 µs ± 170 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
``````

Using `map`

``````In : %timeit(sum(map(lambda xi, yi: xi * yi, x, y)))
12.3 µs ± 144 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
``````

Using `functools.reduce`

``````In : %timeit(sum(functools.reduce(operator.mul, data) for data in zip(*lists)))
38.6 µs ± 330 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
``````