EGM8686
EGM8686

Reputation: 1572

Python SUMPRODUCT of elements in nested list

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

Answers (5)

pylang
pylang

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

knia
knia

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

gold_cy
gold_cy

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

kip
kip

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

Bill
Bill

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

Related Questions