简体   繁体   English

了解带有列表的枚举的reduce

[英]Understanding reduce with enumerate for a list of lists

I am trying to multiply the first number, 1, of the first list, the second number of the second list, 5, and so on for a list of lists. 我试图将第一个列表的第一个数字1与第二个列表的第二个数字5相乘,以此类推。 For example, for [[1, 2, 3], [4, 5, 6], [7, 8, 9]], I'd like to get 1*5*9. 例如,对于[[1、2、3],[4、5、6],[7、8、9]],我想得到1 * 5 * 9。

While there are many possible ways to do this, I wondered how reduce does with enumerate: 尽管有很多可能的方法可以做到这一点,但我想知道枚举如何减少:

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

I would think that a in the beginning is (0, [1,2,3]) so that a[1] is [1,2,3], and a[0] is 0, and so a[1][a[0]] is 1. 我认为a在开始时为(0,[1,2,3]),使得[1]是[1,2,3],和A [0]为0,等等[1] [ a [0]]为1。

However, I get the following exception: 但是,出现以下异常:

return reduce(lambda a, b: a[1][a[0]]*b[1][b[0]], enumerate(mat))
TypeError: 'int' object has no attribute '__getitem__'

Why is a integer? 为什么是a整数?

Your final and intermediate values are simple integers. 您的最终值和中间值是简单的整数。 So you should start with 1 , and then lambda will always get an integer as a , namely the product so far. 因此,您应该从1开始,然后lambda将始终获得一个整数作为a ,即到目前为止的乘积。 And b will be the next enumerated item. b将是下一个列举的项目。 So here's how to do it: 所以这是怎么做的:

>>> reduce(lambda a, b: a * b[1][b[0]],
           enumerate([[1, 2, 3], [4, 5, 6], [7,8,9]]), 1)
45

Python 2 still allows this, btw: Python 2仍然允许这样做,顺便说一句:

>>> reduce(lambda a, (i, b): a * b[i],
           enumerate([[1, 2, 3], [4, 5, 6], [7,8,9]]), 1)
45

So since you're trying to reach a final value of the diagonal numbers multiplied together this is how O'd do it: 因此,由于您尝试达到对角线数字相乘的最终值,因此这是O要做的:

Example: 例:

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

From what you explained in one of the comments - you are trying to multiply the diagonal elements of a matrix and now I understand why you want to 'enumerate' - that's indeed correct 'cos you want to get that index. 从您在其中一条评论中解释的内容(您正在尝试将矩阵的对角线元素相乘,现在我理解了为什么要“枚举”),这确实是您想要获得该索引的“ cos”。 So following code would do that for you. 因此,以下代码将为您做到这一点。

First map gets all the required elements in a list and the reduce then multiplies them to the desired value. 首先,映射将所有必需的元素存储在列表中,然后reduce将它们乘以所需的值。 Note: a couple of caveats, enumerate gives you out a tuple, so you've to add it as (x,y) in the map lambda. 注意:需要说明的是,枚举会给您一个元组,因此您必须在地图lambda中将其添加为(x,y)。

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)

or 要么

reduce(lambda p,q: p*q, [y[x] for (x,y) in enumerate(a)], 1)

Edit: Added a list comprehension version instead of map-lambda. 编辑:添加了列表理解版本而不是map-lambda。

Note the list comprehension version is just about as fast as the above answer (only about 10% slower), for readability, I'd trade that. 请注意,列表理解版本的速度与上述答案差不多(仅慢10%),出于可读性考虑,我希望以此为代价。

Even though Stefan's answer is perfect in functionality, I'd like to point out that ... we are not the compiler, you know. 即使Stefan的回答在功能上是完美的,但我想指出的是……您知道我们不是编译器。 There is no preventing us from writing something more readable that even illustrates what you are trying to do without explaining a thing: 不能阻止我们编写更具可读性的内容,甚至可以说明您尝试做的事情而无需解释:

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)

Looking at the reduce function, now we know that you want to accumulate on the item at column number = row number. 查看reduce函数,现在我们知道您要在列号=行号处累积该项目。 If that doesn't spell diagonal, I don't know what does :) 如果那没有拼成对角线,那我就不知道了:)

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

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