Python 列表推导式

5 投票
3 回答
1518 浏览
提问于 2025-04-16 10:36

可能重复的问题:
用于计算累计总和的列表推导

我正在尝试写一个简洁的列表推导语句来创建一个累积分布函数(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]

撰写回答