Pythonic减少累积和任意lambda函数?

时间:2018-02-19 11:19:32

标签: python lambda functional-programming reduce accumulate

通过积累进行减少的Pythonic方法是什么?

例如,选择R' Reduce()。给定一个列表和一个任意的lambda函数,它允许通过设置accumulate=T产生累积结果的向量而不是最终结果。一个简单的乘法作为lambda函数的例子是(取自this answer):

Reduce(`*`, x=list(5,4,3,2), accumulate=TRUE)
# [1]   5  20  60 120

重要的是可以使用任意lambda函数(如lambda x, y: ...),因此可以使用例如# the source list l = [0.5, 0.9, 0.8, 0.1, 0.1, 0.9] # the lambda function for aggregation can be arbitrary # this one is just made up for the example func = lambda x, y: x * 0.65 + y * 0.35 # the accumulated reduce: # a) the target list with initializer value hardcoded l2 = [l[0]] # b) the loop for i in range(1, len(l)): l2 += [func( l2[i-1], # last value in l2 l[i] # new value from l )] }的解决方案。只使用总和,乘法,否则不会做的伎俩。我无法想出一个Pythonic解决方案来做到这一点,例如Python的itertoolsfunctools,但可能有办法。尽管还有许多关于使用Python进行减少和特别积累的其他问题和答案,但到目前为止我还没有找到一个通用的答案。

使用循环执行带有任意lambda函数的累积reduce的非Pythonic示例可能如下所示:

 .subscribe(res-> {
                      //success case

                    },
                    t -> {
                        if (t instanceof HttpException) {
                           if (((HttpException) t).code() == 422) {
                           String errorResponse=((HttpException) t).response().errorBody().string();
                         //your validations
                        }
                        } else {

                            t.printStackTrace();

                        }
                    });

那么:你如何用Pythonic方式进行累积和任意lambda函数的减少?

1 个答案:

答案 0 :(得分:2)

在Python 3中(在3.2中引入,能够传递3.3中添加的功能)这已在itertools.accumulate中实现。只需使用它:

from itertools import accumulate
list(accumulate([5, 4, 3, 2], lambda a, b: a*b))
# [5, 20, 60, 120]

如果您使用的是早期的Python版本,或者想要自己实现它,并且您真的想要任意lambda(需要两个参数)才能工作,那么您可以使用在上述文件:

def accumulate(iterable, func=operator.add):
    'Return running totals'
    # accumulate([1,2,3,4,5]) --> 1 3 6 10 15
    # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
    it = iter(iterable)
    try:
        total = next(it)
    except StopIteration:
        return
    yield total
    for element in it:
        total = func(total, element)
        yield total

用法与上述完全相同。

如果您使用numpy,则存在更快的解决方案,至少对于所有numpy.ufunc来说都是如此。这些功能基本上与标准库模块math提供的功能相同,然后是一些功能。您可以找到完整列表here

每个numpy.ufunc都有accumulate方法,因此您可以这样做:

import numpy as np
np.multiply.accumulate([5, 4, 3, 2])
# array([  5,  20,  60, 120])