Python 使用累加器和任意 lambda 函数减少?
Pythonic reduce with accumlation and arbitrary lambda function?
Python执行累加归约的 ic 方法是什么?
例如取R
的Reduce()
. Given a list and an arbitrary lambda function it allows for yielding a vector of accumulated results instead of only the final result by setting accumulate=T
. An example for this with a simple multiplication as lambda function would be (taken from ):
Reduce(`*`, x=list(5,4,3,2), accumulate=TRUE)
# [1] 5 20 60 120
重要的是可以使用任意 lambda 函数(如 lambda x, y: ...
),因此解决方案允许例如仅使用求和、乘法或其他方法是行不通的。我无法想出一个 Pythonic 解决方案来做到这一点,例如Python的itertools
or functools
,但也许有办法。尽管还有许多其他关于 reduce 和特别是 Python 积累的问题和答案,但到目前为止我还没有找到通用的答案。
一个非Pythonic 示例,使用循环执行带有任意 lambda 函数的累积归约可能如下所示:
# 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 方式使用累加和任意 lambda 函数进行归约?
在Python3中(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])
Python执行累加归约的 ic 方法是什么?
例如取R
的Reduce()
. Given a list and an arbitrary lambda function it allows for yielding a vector of accumulated results instead of only the final result by setting accumulate=T
. An example for this with a simple multiplication as lambda function would be (taken from
Reduce(`*`, x=list(5,4,3,2), accumulate=TRUE)
# [1] 5 20 60 120
重要的是可以使用任意 lambda 函数(如 lambda x, y: ...
),因此解决方案允许例如仅使用求和、乘法或其他方法是行不通的。我无法想出一个 Pythonic 解决方案来做到这一点,例如Python的itertools
or functools
,但也许有办法。尽管还有许多其他关于 reduce 和特别是 Python 积累的问题和答案,但到目前为止我还没有找到通用的答案。
一个非Pythonic 示例,使用循环执行带有任意 lambda 函数的累积归约可能如下所示:
# 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 方式使用累加和任意 lambda 函数进行归约?
在Python3中(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])