How can I sum the product of two list items using for loop in python?
Question:
I am trying to sum the product of two different list items in the same line using for loop, but I am not getting the output as expected.
My example code:
a = [1,2,3]
b = [4,5,6]
sum = 0 # optional element
score = ((sum+(a(i)*b(i)) for i in range(len(a)))
print score
output:
<generator object <genexpr> at 0x027284B8>
expected output:
32 # 0+(1*4)+(2*5)+(3*6)
Answers:
Just zip
the lists to generate pairs, multiply them and feed to sum
:
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> sum(x * y for x, y in zip(a, b))
32
In above zip
will return iterable of tuples containing one number from both lists:
>>> list(zip(a, b))
[(1, 4), (2, 5), (3, 6)]
Then generator expression is used to multiply the numbers together:
>>> list(x*y for x, y in list(zip(a, b)))
[4, 10, 18]
Finally sum
is used to sum them together for final result:
>>> sum(x*y for x, y in list(zip(a, b)))
32
You have some problems in your code, first off you cant index your list with parenthesis you need []
, secondly you’ve created a generator not a number.
You need to zip
your lists first:
In [3]: sum(i*j for i,j in zip(a, b))
Out[3]: 32
Or as a functional approach use operator.mul
within map
and sum
:
In [11]: from operator import mul
In [12]: sum(map(mul, a, b))
Out[12]: 32
You can try:
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> sum(map(lambda x: x[0] * x[1], zip(a, b)))
32
a = [1,2,3]
b = [4,5,6]
ls = [x * y for x, y in zip(a, b)]
x = sum(ls)
print x
Let’s take a close look at your code:
score = ((sum+(a(i)*b(i)) for i in range(len(a)))
The right hand side of this statement is a generator expression. Think of a generator as a lazy list. It doesn’t actually sum anything, so to be more correct you should do
score = (a[i]*b[i] for i in range(len(a)))
(Note the brackets, not parentheses, for subscripting the lists.)
Now score
is a generator which “contains” the products of corresponding elements of the original lists a
and b
.
The next step is to iterate over the list to sum the elements:
for x in score:
sum += x
print(sum)
As others have already posted, you can do this all in one line with zip()
and sum()
built-in functions:
sum([x*y for x, y in zip(a, b)])
A generator by itself, even if applied so as to generate the list result, will just give you a list of the products. You still need to do something to add up the elements of the list, which you can’t do inside your generator.
Your method looks like you’ve mixed generator syntax with a traditional for
loop, which would look like this:
score = 0
for i in range(len(a)):
score = score + a[i]*b[i]
The cleanest, or at least most Pythonic, solution probably uses zip
to combine the lists, a list comprehension to multiply the elements, and sum
to add them all up:
score = sum([x*y for (x,y) in zip(a,b)])
You could also use reduce
for the full-on functional approach (note that you have to import
it from functools
if you use Python 3):
score = reduce(lambda s,t: s+t[0]*t[1], zip(a,b), 0)
If you have a large list, you might consider taking the dot product using numpy arrays
import numpy as np
arr1 = np.random.randint(0,2,300)
arr2 = np.random.randint(0,2500,300)
list1 = list(arr1)
list2 = list(arr2)
%timeit sum([x * y for x, y in zip(list1,list2)])
38.9 µs ± 795 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit arr1 @ arr2
1.23 µs ± 89.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
an unconventional method: the LAMBDA function.
a = [1,2,3]
b = [4,5,6]
pwr = sum(map(lambda a,b:a*b, a,b))
print(pwr)
Since Python 3.12, there is a new built-in function in the math
module – sumprod
:
from math import sumprod
a = [1,2,3]
b = [4,5,6]
print(sumprod(a, b))
# 32
I am trying to sum the product of two different list items in the same line using for loop, but I am not getting the output as expected.
My example code:
a = [1,2,3]
b = [4,5,6]
sum = 0 # optional element
score = ((sum+(a(i)*b(i)) for i in range(len(a)))
print score
output:
<generator object <genexpr> at 0x027284B8>
expected output:
32 # 0+(1*4)+(2*5)+(3*6)
Just zip
the lists to generate pairs, multiply them and feed to sum
:
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> sum(x * y for x, y in zip(a, b))
32
In above zip
will return iterable of tuples containing one number from both lists:
>>> list(zip(a, b))
[(1, 4), (2, 5), (3, 6)]
Then generator expression is used to multiply the numbers together:
>>> list(x*y for x, y in list(zip(a, b)))
[4, 10, 18]
Finally sum
is used to sum them together for final result:
>>> sum(x*y for x, y in list(zip(a, b)))
32
You have some problems in your code, first off you cant index your list with parenthesis you need []
, secondly you’ve created a generator not a number.
You need to zip
your lists first:
In [3]: sum(i*j for i,j in zip(a, b))
Out[3]: 32
Or as a functional approach use operator.mul
within map
and sum
:
In [11]: from operator import mul
In [12]: sum(map(mul, a, b))
Out[12]: 32
You can try:
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> sum(map(lambda x: x[0] * x[1], zip(a, b)))
32
a = [1,2,3]
b = [4,5,6]
ls = [x * y for x, y in zip(a, b)]
x = sum(ls)
print x
Let’s take a close look at your code:
score = ((sum+(a(i)*b(i)) for i in range(len(a)))
The right hand side of this statement is a generator expression. Think of a generator as a lazy list. It doesn’t actually sum anything, so to be more correct you should do
score = (a[i]*b[i] for i in range(len(a)))
(Note the brackets, not parentheses, for subscripting the lists.)
Now score
is a generator which “contains” the products of corresponding elements of the original lists a
and b
.
The next step is to iterate over the list to sum the elements:
for x in score:
sum += x
print(sum)
As others have already posted, you can do this all in one line with zip()
and sum()
built-in functions:
sum([x*y for x, y in zip(a, b)])
A generator by itself, even if applied so as to generate the list result, will just give you a list of the products. You still need to do something to add up the elements of the list, which you can’t do inside your generator.
Your method looks like you’ve mixed generator syntax with a traditional for
loop, which would look like this:
score = 0
for i in range(len(a)):
score = score + a[i]*b[i]
The cleanest, or at least most Pythonic, solution probably uses zip
to combine the lists, a list comprehension to multiply the elements, and sum
to add them all up:
score = sum([x*y for (x,y) in zip(a,b)])
You could also use reduce
for the full-on functional approach (note that you have to import
it from functools
if you use Python 3):
score = reduce(lambda s,t: s+t[0]*t[1], zip(a,b), 0)
If you have a large list, you might consider taking the dot product using numpy arrays
import numpy as np
arr1 = np.random.randint(0,2,300)
arr2 = np.random.randint(0,2500,300)
list1 = list(arr1)
list2 = list(arr2)
%timeit sum([x * y for x, y in zip(list1,list2)])
38.9 µs ± 795 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit arr1 @ arr2
1.23 µs ± 89.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
an unconventional method: the LAMBDA function.
a = [1,2,3]
b = [4,5,6]
pwr = sum(map(lambda a,b:a*b, a,b))
print(pwr)
Since Python 3.12, there is a new built-in function in the math
module – sumprod
:
from math import sumprod
a = [1,2,3]
b = [4,5,6]
print(sumprod(a, b))
# 32