I have:
a = [[1,2],[3,4],[7,10]]
b = [[8,6],[1,9],[2,1],[8,8]]
I want to multiply (pairwise) every element of a with b
1*8+2*6+1*1+2*9+.....+1*8+2*8+3*8+4*6+......+7*8+10*8
Here's my code so far:
def f(a, b):
new = [x for x in a or x in b]
newer = []
for tuple1, tuple2 in new:
newer.append(map(lambda s,t: s*t, new, new))
return sum(newer)
so my plan of attack was to get all the lists in one list and then multiply everything together. I have seen that lambda work for multiplying lists pairwise but I can't get it to work for the one list.
That kind of combination is called the Cartesian product. I'd use itertools.product
for this, which can easily cope with more than 2 lists, if you want.
Firstly, here's a short demo that shows how to get all of the pairs and how to use tuple assignment to grab the individual elements of the pairs of sublists.
from itertools import product
a = [[1,2],[3,4],[7,10]]
b = [[8,6],[1,9],[2,1],[8,8]]
for (u0, u1), (v0, v1) in product(a, b):
print(u0, u1, v0, v1)
output
1 2 8 6
1 2 1 9
1 2 2 1
1 2 8 8
3 4 8 6
3 4 1 9
3 4 2 1
3 4 8 8
7 10 8 6
7 10 1 9
7 10 2 1
7 10 8 8
And here's how to find the sum
of products that you want.
total = sum(u0 * v0 + u1 * v1 for (u0, u1), (v0, v1) in product(a, b))
print(total)
output
593
Here's an alternative approach, using the distributive property, as mentioned by Prune.
Firstly, here's an unreadable list comprehension version. ;)
a = [[1,2],[3,4],[7,10]]
b = [[8,6],[1,9],[2,1],[8,8]]
print(sum([u*v for u,v in zip(*[[sum(t) for t in zip(*u)] for u in (a, b)])]))
output
593
By the distributive law, the sum you want from the given input data can be written as
(1 + 3 + 7) * (8 + 1 + 2 + 8) + (6 + 9 + 1 + 8) * (2 + 4 + 10)
We can re-arrange the data to produce that expression as follows.
# Use zip to transpose each of the a & b lists.
for u in (a, b):
for t in zip(*u):
print(t)
output
(1, 3, 7)
(2, 4, 10)
(8, 1, 2, 8)
(6, 9, 1, 8)
Now we modify that slightly to get the sums of those lists
# Use zip to transpose each of the a & b lists and compute the partial sums.
partial_sums = []
for u in (a, b):
c = []
for t in zip(*u):
c.append(sum(t))
partial_sums.append(c)
print(partial_sums)
output
[[11, 16], [19, 24]]
Now we just need to multiply the corresponding items of those lists, and add those products together to get the final sum. Once again, we use zip
to perform the transposition.
total = 0
for u, v in zip(*partial_sums):
print(u, v)
total += u * v
print(total)
output
11 19
16 24
593
If your only need is to return that conglomerate sum, I suggest that you quit doing all of that complex work: apply the distributive property. From your example, I'm not sure how thoroughly you are making your cross-products, but this collapses the example to do all elements of each.
sum1 = sum(sum(_) for _ in a)
sum2 = sum(sum(_) for _ in b)
return sum1 * sum2
I suggest stepping back from the code and breaking this down into smaller parts. First, multiply each element from two lists, pairwise.
Second, given a list of lists a
and a list of numbers b
, multiply each list of a
pairwise by b
. This can reuse the solution to part 1.
Finally, solve your original problem with two lists of lists by reusing part 2.
Note how I am describing each of these pieces in words without worrying too much about Python syntax. Now that we have a description in words, it is easier to translate it into Python.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With