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