time_interval = [4, 6, 12]
我想总结一下[4, 4+6, 4+6+12]
这样的数字,以获取列表t = [4, 10, 22]
。
我尝试了以下内容:
for i in time_interval:
t1 = time_interval[0]
t2 = time_interval[1] + t1
t3 = time_interval[2] + t2
print(t1, t2, t3)
4 10 22
4 10 22
4 10 22
答案 0 :(得分:86)
如果你正在对这样的数组进行大量的数值工作,我建议numpy
,它带有累积求和函数cumsum
:
import numpy as np
a = [4,6,12]
np.cumsum(a)
#array([4, 10, 22])
对于这种事情,Numpy通常比纯python更快,与@Ashwini's accumu
比较看:
In [136]: timeit list(accumu(range(1000)))
10000 loops, best of 3: 161 us per loop
In [137]: timeit list(accumu(xrange(1000)))
10000 loops, best of 3: 147 us per loop
In [138]: timeit np.cumsum(np.arange(1000))
100000 loops, best of 3: 10.1 us per loop
但是,如果它是唯一一个你会使用numpy的地方,那么可能不值得依赖它。
答案 1 :(得分:70)
在Python 2中,您可以像这样定义自己的生成器函数:
def accumu(lis):
total = 0
for x in lis:
total += x
yield total
In [4]: list(accumu([4,6,12]))
Out[4]: [4, 10, 22]
在Python 3.2+中,您可以使用itertools.accumulate()
:
In [1]: lis = [4,6,12]
In [2]: from itertools import accumulate
In [3]: list(accumulate(lis))
Out[3]: [4, 10, 22]
答案 2 :(得分:14)
看哪:
a = [4, 6, 12]
reduce(lambda c, x: c + [c[-1] + x], a, [0])[1:]
将输出(如预期的那样):
[4, 10, 22]
答案 3 :(得分:10)
我用Python 3.4做了前两个答案的基准测试,我发现itertools.accumulate
在许多情况下比numpy.cumsum
更快,通常要快得多。但是,正如您从评论中看到的那样,情况并非总是如此,并且很难详尽地探索所有选项。 (如果您有其他感兴趣的基准测试结果,请随意添加评论或编辑此帖子。)
一些时间......
对于短名单accumulate
大约快4倍:
from timeit import timeit
def sum1(l):
from itertools import accumulate
return list(accumulate(l))
def sum2(l):
from numpy import cumsum
return list(cumsum(l))
l = [1, 2, 3, 4, 5]
timeit(lambda: sum1(l), number=100000)
# 0.4243644131347537
timeit(lambda: sum2(l), number=100000)
# 1.7077815784141421
对于较长的列表accumulate
大约快3倍:
l = [1, 2, 3, 4, 5]*1000
timeit(lambda: sum1(l), number=100000)
# 19.174508565105498
timeit(lambda: sum2(l), number=100000)
# 61.871223849244416
如果numpy
array
未投放到list
,accumulate
的速度仍然快2倍:
from timeit import timeit
def sum1(l):
from itertools import accumulate
return list(accumulate(l))
def sum2(l):
from numpy import cumsum
return cumsum(l)
l = [1, 2, 3, 4, 5]*1000
print(timeit(lambda: sum1(l), number=100000))
# 19.18597290944308
print(timeit(lambda: sum2(l), number=100000))
# 37.759664884768426
如果您将导入放在两个函数之外但仍返回numpy
array
,则accumulate
仍然快近2倍:
from timeit import timeit
from itertools import accumulate
from numpy import cumsum
def sum1(l):
return list(accumulate(l))
def sum2(l):
return cumsum(l)
l = [1, 2, 3, 4, 5]*1000
timeit(lambda: sum1(l), number=100000)
# 19.042188624851406
timeit(lambda: sum2(l), number=100000)
# 35.17324400227517
答案 4 :(得分:3)
首先,您需要一个运行的子序列表:
subseqs = (seq[:i] for i in range(1, len(seq)+1))
然后你只需在每个子序列上调用sum
:
sums = [sum(subseq) for subseq in subseqs]
(这不是最有效的方法,因为你要重复添加所有的前缀。但这对大多数用例来说可能无关紧要,如果你没有这种情况就更容易理解想想跑步总数。)
如果您使用的是Python 3.2或更高版本,则可以使用itertools.accumulate
为您执行此操作:
sums = itertools.accumulate(seq)
如果您使用的是3.1或更早版本,则可以直接从文档中复制“等效”来源(除了将next(it)
更改为it.next()
2.5及更早版本。)< / p>
答案 5 :(得分:3)
根据列表的长度和性能,可能会有很多答案。我可以不考虑性能就想到的一种非常简单的方法是:
a = [1, 2, 3, 4]
a = [sum(a[0:x:1]) for x in range(len(a)+1)][1:]
print(a)
[1, 3, 6, 10]
这是通过使用列表理解来实现的,这可能工作得很好,只是在这里我多次添加了子数组,您可能会即兴创作并使其变得简单!
为您的努力加油!
答案 6 :(得分:2)
values = [4, 6, 12]
total = 0
sums = []
for v in values:
total = total + v
sums.append(total)
print 'Values: ', values
print 'Sums: ', sums
运行此代码会给出
Values: [4, 6, 12]
Sums: [4, 10, 22]
答案 7 :(得分:2)
如果你想要一种没有numpy工作的pythonic方式,这将是我的方式
l = [1,2,3,4]
_d={-1:0}
cumsum=[_d.setdefault(idx, _d[idx-1]+item) for idx,item in enumerate(l)]
现在让我们尝试一下,并针对所有其他实现进行测试
import timeit
L=range(10000)
def sum1(l):
cumsum=[]
total = 0
for v in l:
total += v
cumsum.append(total)
return cumsum
def sum2(l):
import numpy as np
return list(np.cumsum(l))
def sum3(l):
return [sum(l[:i+1]) for i in xrange(len(l))]
def sum4(l):
return reduce(lambda c, x: c + [c[-1] + x], l, [0])[1:]
def this_implementation(l):
_d={-1:0}
return [_d.setdefault(idx, _d[idx-1]+item) for idx,item in enumerate(l)]
# sanity check
sum1(L)==sum2(L)==sum3(L)==sum4(L)==this_implementation(L)
>>> True
# PERFORMANCE TEST
timeit.timeit('sum1(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.001018061637878418
timeit.timeit('sum2(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.000829620361328125
timeit.timeit('sum3(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.4606760001182556
timeit.timeit('sum4(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.18932826995849608
timeit.timeit('this_implementation(L)','from __main__ import sum1,sum2,sum3,sum4,this_implementation,L', number=100)/100.
>>> 0.002348129749298096
答案 8 :(得分:1)
试试这个:
result = []
acc = 0
for i in time_interval:
acc += i
result.append(acc)
答案 9 :(得分:1)
在Python3中,要查找第i
个元素所在的列表的累积和
是原始列表中前i + 1个元素的总和,您可以这样做:
a = [4 , 6 , 12]
b = []
for i in range(0,len(a)):
b.append(sum(a[:i+1]))
print(b)
或者您可以使用列表理解:
b = [sum(a[:x+1]) for x in range(0,len(a))]
输出
[4,10,22]
答案 10 :(得分:1)
赋值表达式from PEP 572(适用于Python 3.8)提供了另一种解决方法:
time_interval = [4, 6, 12]
total_time = 0
cum_time = [total_time := total_time + t for t in time_interval]
答案 11 :(得分:1)
尝试一下: 累加功能,与运算符add一起执行运行中的加法。
import itertools
import operator
result = itertools.accumulate([1,2,3,4,5], operator.add)
list(result)
答案 12 :(得分:0)
有点hacky,但似乎有效:
def cumulative_sum(l):
y = [0]
def inc(n):
y[0] += n
return y[0]
return [inc(x) for x in l]
我确实认为内部函数能够修改在外部词法作用域中声明的y
,但是这不起作用,所以我们玩一些讨厌的黑客而不是结构修改。使用发电机可能更优雅。
答案 13 :(得分:0)
无需使用Numpy,您可以直接在数组上循环并累积总和。例如:
a=range(10)
i=1
while((i>0) & (i<10)):
a[i]=a[i-1]+a[i]
i=i+1
print a
结果:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
答案 14 :(得分:0)
def cummul_sum(list_arguement):
cumm_sum_lst = []
cumm_val = 0
for eachitem in list_arguement:
cumm_val += eachitem
cumm_sum_lst.append(cumm_val)
return cumm_sum_lst
答案 15 :(得分:0)
纯python oneliner用于累积总和:
cumsum = lambda X: X[:1] + cumsum([X[0]+X[1]] + X[2:]) if X[1:] else X
这是受recursive cumulative sums启发的递归版本。一些解释:
X[:1]
是一个包含前一个元素的列表,几乎与[X[0]]
相同(后者会抱怨是空列表)。cumsum
调用处理当前元素[1]
和剩余列表,其长度将减少一。if X[1:]
比if len(X)>1
短。测试:
cumsum([4,6,12])
#[4, 10, 22]
cumsum([])
#[]
与累积产品类似:
cumprod = lambda X: X[:1] + cumprod([X[0]*X[1]] + X[2:]) if X[1:] else X
测试:
cumprod([4,6,12])
#[4, 24, 288]
答案 16 :(得分:0)
您可以通过简单的for
循环以线性时间计算累积总和列表:
def csum(lst):
s = lst.copy()
for i in range(1, len(s)):
s[i] += s[i-1]
return s
time_interval = [4, 6, 12]
print(csum(time_interval)) # [4, 10, 22]
标准库的itertools.accumulate
可能是一种更快的替代方法(因为它是用C语言实现的):
from itertools import accumulate
time_interval = [4, 6, 12]
print(list(accumulate(time_interval))) # [4, 10, 22]
答案 17 :(得分:0)
l = [1,-1,3]
cum_list = l
def sum_list(input_list):
index = 1
for i in input_list[1:]:
cum_list[index] = i + input_list[index-1]
index = index + 1
return cum_list
print(sum_list(l))
答案 18 :(得分:-1)
这是另一个有趣的解决方案。这利用了locals()
的理解能力,即在列表理解范围内生成的局部变量:
>>> [locals().setdefault(i, (elem + locals().get(i-1, 0))) for i, elem
in enumerate(time_interval)]
[4, 10, 22]
locals()
每次迭代的外观如下:
>>> [[locals().setdefault(i, (elem + locals().get(i-1, 0))), locals().copy()][1]
for i, elem in enumerate(time_interval)]
[{'.0': <enumerate at 0x21f21f7fc80>, 'i': 0, 'elem': 4, 0: 4},
{'.0': <enumerate at 0x21f21f7fc80>, 'i': 1, 'elem': 6, 0: 4, 1: 10},
{'.0': <enumerate at 0x21f21f7fc80>, 'i': 2, 'elem': 12, 0: 4, 1: 10, 2: 22}]
对于小型列表而言,性能并不糟糕
>>> %timeit list(accumulate([4, 6, 12]))
387 ns ± 7.53 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> %timeit np.cumsum([4, 6, 12])
5.31 µs ± 67.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> %timeit [locals().setdefault(i, (e + locals().get(i-1,0))) for i,e in enumerate(time_interval)]
1.57 µs ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
显然,对于较大的列表来说,价格会下降。
>>> l = list(range(1_000_000))
>>> %timeit list(accumulate(l))
95.1 ms ± 5.22 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit np.cumsum(l)
79.3 ms ± 1.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit np.cumsum(l).tolist()
120 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit [locals().setdefault(i, (e + locals().get(i-1, 0))) for i, e in enumerate(l)]
660 ms ± 5.14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
尽管该方法很丑陋而且不切实际,但肯定很有趣。
答案 19 :(得分:-1)
In [42]: a = [4, 6, 12]
In [43]: [sum(a[:i+1]) for i in xrange(len(a))]
Out[43]: [4, 10, 22]
slighlty 比上面的@Ashwini对小列表的生成器方法更快
In [48]: %timeit list(accumu([4,6,12]))
100000 loops, best of 3: 2.63 us per loop
In [49]: %timeit [sum(a[:i+1]) for i in xrange(len(a))]
100000 loops, best of 3: 2.46 us per loop
对于较大的列表,生成器是确定的方法。 。 。
In [50]: a = range(1000)
In [51]: %timeit [sum(a[:i+1]) for i in xrange(len(a))]
100 loops, best of 3: 6.04 ms per loop
In [52]: %timeit list(accumu(a))
10000 loops, best of 3: 162 us per loop
答案 20 :(得分:-1)
lst = [4,6,12]
[sum(lst[:i+1]) for i in xrange(len(lst))]
如果您正在寻找更有效的解决方案(更大的列表?),那么生成器可能是一个很好的调用(如果您真的关心perf,则只需使用numpy
。
def gen(lst):
acu = 0
for num in lst:
yield num + acu
acu += num
print list(gen([4, 6, 12]))
答案 21 :(得分:-2)
这将是Haskell风格:
def wrand(vtlg):
def helpf(lalt,lneu):
if not lalt==[]:
return helpf(lalt[1::],[lalt[0]+lneu[0]]+lneu)
else:
lneu.reverse()
return lneu[1:]
return helpf(vtlg,[0])