通过列举列表的枚举来理解reduce

时间:2015-05-21 03:15:03

标签: python list reduce enumerate

我正在尝试将第一个列表的第一个数字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是整数?

4 个答案:

答案 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函数,现在我们知道您希望在列号=行号上累积项目。如果这不是拼写对角线,我不知道是什么:)