map()和filter()在应用单个元素的函数时是很好的,但是在可迭代对象上无法对它们执行以下任何操作:
- 将函数应用于一组元素
- 跟踪先前迭代的元素/'累积'项
- 获取迭代下当前元素的索引
当您需要基于前一个值对当前元素执行操作或对一组元素(如子数组)执行操作时,所有这些都构成了挑战。
example1:我想迭代并逐个求和元素
>>> 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
不可能,因为sum不能对单个int进行操作,并且到目前为止没有办法跟踪迭代值!
示例2:我维护一个局部变量来跟踪当前的和>>> curr = 0
>>> [* map(lambda x: curr+=x ,l)]
^
File "<stdin>", line 1
SyntaxError: invalid syntax
也是不允许的,因为在lambda中不允许赋值或修改!
这两个结果都是预期的,但是是否有一个更容易的函数替代,通常是javascript的reduce()函数所做的?
标准库中有functools.reduce
。您可以将其与lambda
功能一起使用,也可以使用operator
模块提供的各种功能。例如:
>>> from functools import reduce
>>> import operator as op
>>> reduce(op.add, [4,7,2,8,10])
31
但是对于这个特定的用例,已经有内置函数sum
:
>>> sum([4,7,2,8,10])
31
对于累加值,有itertools.accumulate
。
如果你也需要元素的索引,你可以使用enumerate
。