这不会有任何显式循环或致电max
功能。该函数假定输入列表中至少有五个元素,并输出一个元组(start_index, max_product)
。
from functools import reduce, partial
import operator
def f(l):
win = zip(l, l[1:], l[2:], l[3:], l[4:])
products = map(partial(reduce, operator.mul), win)
return reduce(lambda x, y: x if x[1] > y[1] else y, enumerate(products))
In [2]: f([1, 2, 3, 4, 7, 8, 9])
Out[2]: (2, 6048)
In [3]: f([2, 6, 7, 9, 1, 4, 3, 5, 6, 1, 2, 4])
Out[3]: (1, 1512)
win = zip(l, l[1:], l[2:], l[3:], l[4:])
创建在输入列表大小5的滑动窗口迭代器。 products = map(partial(reduce, operator.mul), win)
是在win
的每个元素上调用partial(reduce, operator.mul)
(转换为reduce(operator.mul, ...)
)的迭代器。 reduce(lambda x, y: x if x[1] > y[1] else y, enumerate(products))
将计数器添加到products
并返回具有最高值的索引 - 值对。
如果你需要一个更一般的版本和/或输入列表很大,你会使用itertools.islice
:
from itertools import islice
def f(l, n=5):
win = zip(*(islice(l, i, None) for i in range(n)))
...
上面的代码使用生成器表达式这是一个循环,在技术上。这方面的一个纯功能的版本可能看起来像
from itertools import islice
def f(l, n=5):
win = zip(*map(lambda i: islice(l, i, None), range(n)))
...
'map'和'reduce'使用'loops'幕后,试图避免'列表comprehensions'例如使用循环将要相当困难,并没有真正的好处。 –
如果您使用递归,您几乎可以直接避免循环。 Haskell这样做。但是,Haskell对此进行了优化,Python可能不会。所以你会很快进入最大递归深度。 - 无论如何,你在动作风格上做什么动机? –
函数式编程=/=避免循环。 – trincot