113
time_interval = [4, 6, 12]

I want to sum up the numbers like [4, 4+6, 4+6+12] in order to get the list t = [4, 10, 22].

I tried the following:

t1 = time_interval[0]
t2 = time_interval[1] + t1
t3 = time_interval[2] + t2
print(t1, t2, t3)  # -> 4 10 22
4

23 に答える 23

111

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]
于 2013-04-08T21:19:42.960 に答える
26

Python 3.4 で上位 2 つの回答のベンチマークを行ったところ、多くの状況下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

インポートを 2 つの関数の外に置いても , を返す場合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
于 2016-09-16T15:12:20.087 に答える
21

機能をお試しください itertools.accumulate()

import itertools  

list(itertools.accumulate([1,2,3,4,5]))
# [1, 3, 6, 10, 15]
于 2018-12-13T03:51:43.827 に答える
20

見よ:

a = [4, 6, 12]
reduce(lambda c, x: c + [c[-1] + x], a, [0])[1:]

出力します(予想どおり):

[4, 10, 22]
于 2015-10-09T09:43:50.107 に答える
11

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]
于 2019-03-23T16:59:46.360 に答える
5

Python 3.8から代入式が使えるようになったので、このような実装がしやすくなりました。

nums = list(range(1, 10))
print(f'array: {nums}')

v = 0
cumsum = [v := v + n for n in nums]
print(f'cumsum: {cumsum}')

生産する

array: [1, 2, 3, 4, 5, 6, 7, 8, 9]
cumsum: [1, 3, 6, 10, 15, 21, 28, 36, 45]

同じ手法を適用して、積、平均などを見つけることができます。

p = 1
cumprod = [p := p * n for n in nums]
print(f'cumprod: {cumprod}')

s = 0
c = 0
cumavg = [(s := s + n) / (c := c + 1) for n in nums]
print(f'cumavg: {cumavg}')

結果は

cumprod: [1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
cumavg: [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]
于 2021-08-16T10:18:44.197 に答える
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 以前を使用している場合は、「同等の」ソースをドキュメントから直接コピーできます ( 2.5 以前のへの変更next(it)を除く)。it.next()

于 2013-04-08T21:19:58.600 に答える
3

リストの長さとパフォーマンスに応じて、これには多くの答えがある可能性があります。パフォーマンスを考えずに考えることができる 1 つの非常に単純な方法は次のとおりです。

a = [1, 2, 3, 4]
a = [sum(a[0:x]) for x in range(1, len(a)+1)]
print(a)

[1, 3, 6, 10]

これはリスト内包表記を使用することによるものであり、これはかなりうまく機能する可能性があります。ここでは部分配列を何度も追加しているだけなので、即興でこれを簡単にすることができます!

あなたの努力に乾杯!

于 2020-05-06T13:47:37.853 に答える
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]
于 2013-04-08T21:21:29.280 に答える
1

これを試して:

result = []
acc = 0
for i in time_interval:
    acc += i
    result.append(acc)
于 2013-04-08T21:21:00.723 に答える
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]
于 2014-02-11T15:26:13.867 に答える
0

ややハックですが、うまくいくようです:

def cumulative_sum(l):
  y = [0]
  def inc(n):
    y[0] += n
    return y[0]
  return [inc(x) for x in l]

y内側の関数は外側のレキシカルスコープで宣言されたものを変更できると思っていましたが、うまくいきませんでした。ジェネレーターを使用する方がおそらくよりエレガントです。

于 2013-12-30T09:52:58.720 に答える
0
lst = [4, 6, 12]

[sum(lst[:i+1]) for i in xrange(len(lst))]

より効率的な解決策 (より大きなリスト?) を探している場合は、ジェネレーターが適切な呼び出しになる可能性があります (またはnumpy、パフォーマンスを本当に気にする場合は単に使用してください)。

def gen(lst):
    acu = 0
    for num in lst:
        yield num + acu
        acu += num

print list(gen([4, 6, 12]))
于 2013-04-08T21:24:52.203 に答える
0
In [42]: a = [4, 6, 12]

In [43]: [sum(a[:i+1]) for i in xrange(len(a))]
Out[43]: [4, 10, 22]

これは、小さなリストの場合、@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
于 2013-04-08T21:27:28.730 に答える
0

以下のコードが最も簡単だと思います。

a=[1,1,2,1,2]
b=[a[0]]+[sum(a[0:i]) for i in range(2,len(a)+1)]
于 2022-02-11T13:44:47.280 に答える
-3

This would be Haskell-style:

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])
于 2016-05-14T04:34:35.117 に答える