我正在尝试将第一个列表的第一个数字1,第二个列表的第二个数字,5等相乘,以获得列表列表。例如,对于[[1,2,3],[4,5,6],[7,8,9]],我想获得1 * 5 * 9。
虽然有很多可能的方法可以做到这一点,但我想知道如何使用枚举进行reduce:
def test(m):
return reduce(lambda a, b: a[1][a[0]]*b[1][b[0]], enumerate(m))
print test([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
我认为开头a
是(0,[1,2,3])所以a [1]是[1,2,3],a [0]是0,所以[1] [a [0]]是1.
但是,我得到以下例外:
return reduce(lambda a, b: a[1][a[0]]*b[1][b[0]], enumerate(mat))
TypeError: 'int' object has no attribute '__getitem__'
为什么a
是整数?
答案 0 :(得分:5)
您的最终值和中间值是简单整数。所以你应该从1
开始,然后lambda将始终得到一个整数a
,即到目前为止的产品。 b
将成为下一个枚举项。所以这是如何做到的:
>>> reduce(lambda a, b: a * b[1][b[0]],
enumerate([[1, 2, 3], [4, 5, 6], [7,8,9]]), 1)
45
Python 2仍允许这样做,顺便说一下:
>>> reduce(lambda a, (i, b): a * b[i],
enumerate([[1, 2, 3], [4, 5, 6], [7,8,9]]), 1)
45
答案 1 :(得分:1)
所以,既然你试图达到对角线数的最终值,那么这就是O'd的做法:
示例:强>
def idiagonal(xs_of_ys):
for i, x in enumerate(xs_of_ys):
for j, y in enumerate(x):
if i == j:
yield y
print reduce(lambda x, y: x * y, idiagonal(xs), 1) # prints 45
答案 2 :(得分:0)
根据你在其中一条评论中的解释 - 你试图将矩阵的对角线元素相乘,现在我明白为什么你要'枚举' - 这确实是正确的'因为你想得到那个索引。所以下面的代码会为你做到这一点。
第一张地图获取列表中的所有必需元素,然后reduce将它们乘以所需的值。注意:一些警告,枚举会给你一个元组,所以你要把它作为(x,y)添加到地图lambda中。
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
reduce(lambda p,q: p*q, map(lambda (x,y): y[x], enumerate(a)), 1)
或
reduce(lambda p,q: p*q, [y[x] for (x,y) in enumerate(a)], 1)
编辑:添加了列表推导版本而不是map-lambda。
请注意,列表理解版本的速度与上述答案一样快(仅慢约10%),为了便于阅读,我会交换它。
答案 3 :(得分:0)
尽管Stefan的答案在功能上是完美的,但我想指出......我们不是编译器,你知道。没有阻止我们写一些更具可读性的东西,甚至可以解释你试图做的事情而不解释一件事:
from collections import namedtuple
Row = namedtuple('Row', ['num', 'columns'])
m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
reduce(lambda result, row: result * row.columns[row.num],
(Row(*data) for data in enumerate(m)), 1)
查看reduce函数,现在我们知道您希望在列号=行号上累积项目。如果这不是拼写对角线,我不知道是什么:)