Reputation: 1572
I have two nested lists:
a = [[1,2,3],[2,4,2]]
b = [[5,5,5],[1,1,1]]
I want to multiply and SUMPRODUCT each group of elements to get
c = [[30],[8]]
Which result from = [[1*5+2*5+3*5],[2*1,4*1,2*1]]
I´ve tried doing:
c = sum(x * y for x, y in zip(a, b))
But I get "can't multiply sequence by non-int of type 'list'"
Is there a simple list comprehension way to do this avoiding for loops?
Upvotes: 8
Views: 21867
Reputation: 44585
UPDATE Use math.sumprod()
in Python 3.12+, roughly equivalent to
sum(itertools.starmap(operator.mul, zip(vec1, vec2, strict=True)))
See @knia's solution.
Implement the dotproduct
itertools recipes (removed in Python 3.11):
import operator
def dotproduct(vec1, vec2):
return sum(map(operator.mul, vec1, vec2))
Code
a = [[1,2,3], [2,4,2]]
b = [[5,5,5], [1,1,1]]
[[dotproduct(x, y)] for x, y in zip(a, b)]
# [[30], [8]]
Upvotes: 5
Reputation: 749
Python 3.12 introduced math.sumprod:
>>> import math
>>> a = [[1, 2, 3], [2, 4, 2]]
>>> b = [[5, 5, 5], [1, 1, 1]]
>>> [math.sumprod(x, y) for x, y in zip(a, b)]
[30, 8]
In older versions, I think
>>> [sum(e0 * e1 for e0, e1 in zip(row_a, row_b))
for row_a, row_b in zip(a, b)]
[30, 8]
reads more easily than the map
/reduce
solutions suggested elsewhere.
If you really need extra inner lists like [[30], [8]]
(why?), then add an extra []
somewhere.
Upvotes: 1
Reputation: 14236
Numpy solution
import numpy as np
c = map(lambda x: sum(np.prod((np.array(x)), axis=0)), zip(a,b))
[30, 8]
If you need to produce [[30], [8]]
then
c = map(lambda x: [sum(np.prod((np.array(x)), axis=0))], zip(a,b))
Upvotes: 1
Reputation: 1140
Without numpy
A solution with list comprehension, maybe will this:
a = [[1,2,3],[2,4,2]]
b = [[5,5,5],[1,1,1]]
c = [[sum(map(lambda m: reduce(lambda h,i: h * i, m), n))] for n in [zip(x, y) for x, y in zip(a, b)]]
And show me:
[[30], [8]]
Another more clean solution is a simple for loop
a = [[1,2,3],[2,4,2]]
b = [[5,5,5],[1,1,1]]
c = []
for x, y in zip(a, b):
temp = []
for m, n in zip(x,y):
temp.append(m * n)
c.append([sum(temp)])
Result:
[[30], [8]]
Sorry for not readable variable names, I recommend the simple for
in this cases
Upvotes: 1
Reputation: 11643
You could do it with a nested list comprehension but it would be complicated. Here it is one step at a time.
a = [[1,2,3],[2,4,2]]
b = [[5,5,5],[1,1,1]]
result1 = [[x*y for x, y in zip(r1, r2)] for r1, r2 in zip(a, b)]
c = [[sum(r)] for r in result1]
c
[[30], [8]]
Upvotes: 0