乘以不同长度的列表列表

时间:2018-02-12 18:13:46

标签: python

我有:

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

我想乘以(成对)a的每个元素与b

1*8+2*6+1*1+2*9+.....+1*8+2*8+3*8+4*6+......+7*8+10*8

到目前为止,这是我的代码:

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)

所以我的攻击计划是将所有列表放在一个列表中然后将所有内容相乘。我已经看到lambda用于成对地增加列表,但我不能让它适用于一个列表。

6 个答案:

答案 0 :(得分:10)

这种组合被称为笛卡尔积。我会使用itertools.product,如果你愿意,可以轻松应对2个以上的列表。

首先,这是一个简短的演示,演示了如何获取所有对以及如何使用元组赋值来获取子列表对中的各个元素。

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)

<强>输出

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

以下是如何找到您想要的sum产品。

total = sum(u0 * v0 + u1 * v1 for (u0, u1), (v0, v1) in product(a, b))
print(total)

<强>输出

593

这是另一种使用分配属性的方法,如Prune所述。

首先,这是一个不可读的列表理解版本。 ;)

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)])]))

<强>输出

593

如何运作

根据分配法,您希望从给定输入数据中得到的总和可以写为

(1 + 3 + 7) * (8 + 1 + 2 + 8) + (6 + 9 + 1 + 8) * (2 + 4 + 10)

我们可以重新排列数据以生成该表达式,如下所示。

# Use zip to transpose each of the a & b lists.
for u in (a, b):
    for t in zip(*u):
        print(t)

<强>输出

(1, 3, 7)
(2, 4, 10)
(8, 1, 2, 8)
(6, 9, 1, 8)

现在我们稍微修改一下以获得这些列表的总和

# 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)        

<强>输出

[[11, 16], [19, 24]]

现在我们只需要将这些列表的相应项目相乘,并将这些产品加在一起以获得最终总和。我们再一次使用zip来执行转置。

total = 0
for u, v in zip(*partial_sums):
    print(u, v)
    total += u * v
print(total)        

<强>输出

11 19
16 24
593

答案 1 :(得分:5)

如果您唯一的需要是返回该集团总和,我建议您放弃完成所有这些复杂的工作:应用分配属性。从您的示例来看,我不确定您制作交叉产品有多彻底,但这会折叠示例以完成每个元素的所有元素。

sum1 = sum(sum(_) for _ in a)
sum2 = sum(sum(_) for _ in b)
return sum1 * sum2

答案 2 :(得分:1)

我建议从代码中退一步,将其分解为更小的部分。首先,将两个列表中的每个元素成对地相乘。

其次,给定列表a列表和数字列表b,将a成对的每个列表乘以b。这可以将解决方案重用到第1部分。

最后,通过重用第2部分,用两个列表列表解决原始问题。

请注意我是如何描述中的每个 ,而不必过多担心Python语法。现在我们用文字描述了,将它翻译成Python更容易。

答案 3 :(得分:1)

使用numpy可以轻而易举地解决这个问题:

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

答案 4 :(得分:0)

为了简化操作,您可以使用itertools.product功能。

它的作用是返回像参数一样传递给它的迭代的笛卡尔积。拥有笛卡儿积之后,你可以迭代它们并做一对坐标。

解释之后,这是你想要的东西:

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

答案 5 :(得分:0)

您可以将import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; export class btnInfo { public text: string; public clickFn: string; } export class messageInfo { public text: string; public background: string; public timeout: number; // milliseconds; 0 is none public btns: Array<string>; // button labels } @Component({ selector: 'sh-msg-bar', templateUrl: './msg-bar.component.html', styleUrls: ['./msg-bar.component.scss'] }) export class MsgBarComponent implements OnInit { @Input() name=''; @Input() title=''; @Input() color='black'; @Input() bcolor='white'; @Input() timeout='0'; @Input() buttons: Array<string>; @Input() brdcolor:'gray'; @Output() msgEvent = new EventEmitter(); isHidden = false; isEmpty = false; constructor() { } ngOnInit() { if (Number(this.timeout) > 0) { setTimeout(() => { this.isEmpty = true; }, Number(this.timeout)); } } toggleHidden() { this.isHidden = !this.isHidden; } doBtnEvent(title: string) { console.log(title); } } itertools.product

一起使用
zip