map() and filter() are good when it comes to applying a function individual elements, but there is no way to do any of the following with them on iterables :
- apply functions on a bunch of elements as a whole
- keep track of previously iterated elements / ‘accumulate’ items
- get the index of the current element under iteration
All of these pose a challenge when you need to perform operations on the current element based on previous values or on a group of elements together like a sub-array.
example1 : I want to iterate over and sum the elements one by one
>>> l = [4,7,2,8,10] >>> map(sum,l) # throws the following error Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 1, in <lambda> TypeError: 'int' object is not iterable
Not possible since sum cannot operate on single ints and there is no way to track the iterated values up till now!
example 2: I maintain a local variable to track the current sum
>>> curr = 0 >>> [* map(lambda x: curr+=x ,l)] ^ File "<stdin>", line 1 SyntaxError: invalid syntax
Again, not allowed since assignment or modification not allowed inside lambda!
Both of these results are expected, but is there an easier functional alternative which is typically what the javascript reduce() function does?
Advertisement
Answer
There is functools.reduce
in the standard library. You can use it together with a lambda
function or use the various functions provided by the operator
module. For example:
>>> from functools import reduce >>> import operator as op >>> reduce(op.add, [4,7,2,8,10]) 31
But for that specific use case there is already the builtin function sum
:
>>> sum([4,7,2,8,10]) 31
For accumulating values there is itertools.accumulate
.
If you need the elements’ indices as well, you can use enumerate
.