Python 列表推导式
可能重复的问题:
用于计算累计总和的列表推导
我正在尝试写一个简洁的列表推导语句来创建一个累积分布函数(cdf):
举个例子:
print f([0.2, 0.3,0.1,0.4])
[0.2,0.5,0.6,1.0]
一个标准的做法看起来像这样(我想为函数 f() 写一个列表推导):
def f(probabilities) :
sum = 0
returnList = []
for count in probabilities:
sum +=count
returnList = returnList + [sum]
return returnList
补充:我发现了一个函数 numpy.cumsum()。我会检查它是否使用了列表推导。
3 个回答
1
这个方法看起来不是很好,而且没有用到列表推导式,但你可以用reduce()函数来实现。在这里,累积的值是一个元组,里面保存了当前的总和和结果列表:
a = [0.2, 0.3, 0.1, 0.4]
reduce((lambda result, val: (result[0] + val, result[1] + [result[0] + val])), a, (0, []))[1]
因为Python不支持多行的lambda表达式,所以这个写法有点丑。用一个单独的函数会更好:
a = [0.2, 0.3, 0.1, 0.4]
def accumulate(result, val):
return (result[0] + val, result[1] + [result[0] + val])
reduce(accumulate, a, (0, []))[1]
6
[sum(probabilities[:i+1]) for i in range(len(probabilities))]
但是不要这样做,因为这样效率很低,是O(n^2)。Python的列表推导式并不是为了这个目的设计的。还是用你已经写好的过程代码吧。
8
这个操作非常常见,所以很多编程语言(主要是函数式编程语言,但不仅限于此)都提供了类似的功能,通常叫做 scanl
(它就像是一个带有中间结果的 reduce
)。我们可以把它称为 ireduce
(意为“迭代减少”):
def ireduce(f, state, it):
for x in it:
state = f(state, x)
yield state
现在来使用它:
import operator
def f(probabilities):
return ireduce(operator.add, 0, probabilities)
print(list(f([0.2, 0.3,0.1,0.4])))
# [0.2, 0.5, 0.6, 1.0]