Search code examples
pythonlistreduceenumerate

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. For example, for [[1, 2, 3], [4, 5, 6], [7, 8, 9]], I'd like to get 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.

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?


Solution

  • 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. And b will be the next enumerated item. 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:

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