reduce function gives unexpected result in a 2d list in python

Question:

hi guys I wrote this small code , and in my understanding of the reduce function this code should give me the total of the the prices but it doesn’t can any one explain what’s going on.

import functools
bill = [["jaket" , 2500, 2] , ["ball" , 450 , 1] , ["calculator" , 120 , 4]]
lmbd_total = lambda data1 , data2 : data1[1]+data2[1]
totall = functools.reduce(lmbd_total , bill)
print(totall)
Asked By: kamal douma

||

Answers:

reduce works like chaining, the result from the previous sum goes into the next invocation. So when you return an int from the first sum, it will be passed to the next call as data1. When it tries to do data1[1], it will fail.

So you’ll have to return something that "looks like" the data you are passing to reduce:

import functools

bill = [["jaket", 2500, 2], ["ball", 450, 1], ["calculator", 120, 4]]
lmbd_total = lambda data1, data2: (None, data1[1] + data2[1], None)
totall = functools.reduce(lmbd_total, bill)
print(totall[1])

Which is quite ugly-looking. You can get the same result with a simple sum():

bill = [["jaket", 2500, 2], ["ball", 450, 1], ["calculator", 120, 4]]
totall = sum(a[1] for a in bill)
print(totall)
Answered By: rdas

lmbd_total = lambda data1 , data2 : data1[1]+data2[1]

The first iteration will add correctly. But the second iteration, the accumulator data1 is a int object and not a list. Therefore, data1[1] is not subscriptable. Add a int as initializer and make the accumulator constant type int .

bill = [["jaket" , 2500, 2] , ["ball" , 450 , 1] , ["calculator" , 120 , 4 ]]
lmbd_total = lambda acc , data2 : acc+data2[1]
totall = functools.reduce(lmbd_total , bill,0)
print(totall)
Answered By: TheMaster

Now that you got your answer, maybe it is also nice to know accumulate method from itertools which basically does the same this as functools.reduce as specified by TheMaster‘s concise and to the point answer. The only difference is that accumualte also returns intermediate values that could be suitable where you are working with data frames and would like to populate a new column based on other columns:

from itertools import accumulate

list(accumulate(bill, lambda x, y: x + y[1], initial = 0))

[0, 2500, 2950, 3070]
Answered By: Anoushiravan R
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.