简体   繁体   English

乘以不同长度的列表列表

[英]multiplying lists of lists with different lengths

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 我想用a乘以(成对)a的每个元素

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. 我已经看到lambda用于成对地增加列表,但我不能让它适用于一个列表。

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. 我会使用itertools.product ,如果你愿意,可以轻松应对2个以上的列表。

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. 以下是如何找到所需产品的sum

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. 这是一种替代方法,使用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

How it works 这个怎么运作

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. 我们再次使用zip来执行转置。

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 . 第二,由于名单列表a和编号的列表b ,乘的每个列表a两两b This can reuse the solution to part 1. 这可以将解决方案重用到第1部分。

Finally, solve your original problem with two lists of lists by reusing part 2. 最后,通过重用第2部分,用两个列表列表解决原始问题。

Note how I am describing each of these pieces in words without worrying too much about Python syntax. 请注意我是如何用文字描述这些部分的而不必过多担心Python语法。 Now that we have a description in words, it is easier to translate it into Python. 现在我们用文字描述了,将它翻译成Python更容易。

Using numpy will knock this out trivially: 使用numpy可以轻而易举地解决这个问题:

>>> a = np.array(a)
>>> b = np.array(b)
>>> (a @ b.T).sum()
593

To make things easier, you can use itertools.product function. 为了itertools.product ,您可以使用itertools.product函数。

What it does is that it returns Cartesian product of iterables passed to it like arguments. 它的作用是返回像参数一样传递给它的迭代的笛卡尔积。 After you have Cartesian product, you can iterate through them and do sum of pairs of coordinates. 拥有笛卡儿积之后,您可以迭代它们并对坐标进行求和。

After explanation, this is something that you want: 解释后,这是你想要的东西:

from itertools import product


a = [[1, 2], [3, 4], [7, 10]]
b = [[8, 6], [1, 9], [2, 1], [8, 8]]


def multiply(a, b):
    sum = 0
    for pair1, pair2 in product(a, b):
        sum += pair1[0]*pair2[0] + pair1[1]*pair2[1]
    return sum


print multiply(a, b) #  593

You can use itertools.product with zip : 你可以使用带有zip itertools.product

import itertools
a=[[1,2],[3,4],[7,10]]
b=[[8,6],[1,9],[2,1],[8,8]]
result = sum(sum(c*d for c, d in zip(h, k)) for h, k in itertools.product(a, b))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM