web-dev-qa-db-de.com

Wie finde ich die kumulierte Summe der Zahlen in einer Liste?

time_interval = [4, 6, 12]

Ich möchte die Zahlen wie [4, 4+6, 4+6+12] zusammenfassen, um die Liste t = [4, 10, 22] zu erhalten.

Ich habe folgendes versucht:

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
56
user2259323

Wenn Sie mit Arrays wie diesem viel arbeiten, würde ich numpy vorschlagen, das mit einer Summenfunktion cumsum geliefert wird.

import numpy as np

a = [4,6,12]

np.cumsum(a)
#array([4, 10, 22])

Numpy ist für solche Dinge oft schneller als reiner Python, siehe im Vergleich zu @ Ashwinis 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

Aber wenn dies der einzige Ort ist, an dem Sie numpy verwenden, lohnt es sich möglicherweise nicht, davon abhängig zu sein.

80
askewchan

In Python 2 können Sie Ihre eigene Generatorfunktion folgendermaßen definieren:

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]

In Python 3.2 und höher können Sie itertools.accumulate() verwenden:

In [1]: lis = [4,6,12]

In [2]: from itertools import accumulate

In [3]: list(accumulate(lis))
Out[3]: [4, 10, 22]
66

Erblicken:

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

Wird ausgegeben (wie erwartet):

[4, 10, 22]
15
wonder.mice

Ich habe mit Python 3.4 ein Benchmarking der ersten beiden Antworten durchgeführt und fand, dass itertools.accumulate unter vielen Umständen schneller als numpy.cumsum ist, oft viel schneller. Wie Sie in den Kommentaren sehen können, ist dies möglicherweise nicht immer der Fall, und es ist schwierig, alle Optionen ausführlich zu untersuchen. (Fühlen Sie sich frei, einen Kommentar hinzuzufügen oder diesen Beitrag zu bearbeiten, wenn Sie weitere Benchmark-Ergebnisse von Interesse haben.)

Einige Timings ...

Für Kurzlisten ist accumulate etwa viermal schneller:

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

Bei längeren Listen ist accumulate etwa dreimal schneller:

l = [1, 2, 3, 4, 5]*1000
timeit(lambda: sum1(l), number=100000)
# 19.174508565105498
timeit(lambda: sum2(l), number=100000)
# 61.871223849244416

Wenn numpyarray nicht in list umgewandelt wird, ist accumulate noch ungefähr 2-mal schneller:

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

Wenn Sie die Importe außerhalb der beiden Funktionen ablegen und trotzdem eine numpyarray zurückgeben, ist accumulate noch fast zwei Mal schneller:

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
9
Chris_Rands

Zunächst möchten Sie eine laufende Liste von Untersequenzen:

subseqs = (seq[:i] for i in range(1, len(seq)+1))

Dann rufen Sie einfach sum in jeder Untersequenz auf:

sums = [sum(subseq) for subseq in subseqs]

(Dies ist nicht die effizienteste Methode, da Sie alle Präfixe wiederholt hinzufügen. In den meisten Anwendungsfällen ist dies jedoch wahrscheinlich unwichtig und es ist einfacher zu verstehen, wenn Sie nicht darüber nachdenken müssen die laufenden Summen.)

Wenn Sie Python 3.2 oder neuer verwenden, können Sie itertools.accumulate verwenden, um dies für Sie auszuführen:

sums = itertools.accumulate(seq)

Wenn Sie 3.1 oder eine frühere Version verwenden, können Sie einfach die Quelle "Äquivalent zu" direkt aus den Dokumenten kopieren (mit Ausnahme der Änderung von next(it) in it.next() für 2.5 und früher).

3
abarnert

Wenn Sie einen pythonischen Weg möchten, ohne in 2.7 arbeiten zu müssen, ist dies meine Art, dies zu tun

l = [1,2,3,4]
_d={-1:0}
cumsum=[_d.setdefault(idx, _d[idx-1]+item) for idx,item in enumerate(l)]

jetzt versuchen wir es und testen es mit allen anderen Implementierungen

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
2
Cobry
values = [4, 6, 12]
total  = 0
sums   = []

for v in values:
  total = total + v
  sums.append(total)

print 'Values: ', values
print 'Sums:   ', sums

Das Ausführen dieses Codes gibt an

Values: [4, 6, 12]
Sums:   [4, 10, 22]
2
Chris Taylor

Zuweisungsausdrücke von PEP 572 (für Python 3.8 erwartet) bieten eine weitere Möglichkeit, dies zu lösen:

time_interval = [4, 6, 12]

total_time = 0
cum_time = [total_time := total_time + t for t in time_interval]
1

Versuche dies:

result = []
acc = 0
for i in time_interval:
    acc += i
    result.append(acc)
1
MostafaR

Etwas hackig, scheint aber zu funktionieren:

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

Ich dachte schon, dass die innere Funktion die im äußeren lexikalischen Geltungsbereich deklarierte y ändern könnte, aber das hat nicht funktioniert, also spielen wir einige böse Hacks mit Strukturänderung. Es ist wahrscheinlich eleganter, einen Generator zu verwenden.

0
Vatine
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
0
Ronnie Joshua

Um in Python3 die kumulative Summe einer Liste zu ermitteln, in der das ith-Element die Summe der ersten i + 1-Elemente aus der ursprünglichen Liste ist, können Sie Folgendes tun:

a = [4 , 6 , 12]
b = []
for i in range(0,len(a)):
    b.append(sum(a[:i+1]))
print(b)

ODER Sie können das Listenverständnis verwenden:

b = [sum(a[:x+1]) for x in range(0,len(a))]

Ausgabe

[4,10,22]
0
manish apte
lst = [4,6,12]

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

Wenn Sie nach einer effizienteren Lösung suchen (größere Listen?), Könnte ein Generator ein guter Aufruf sein (oder verwenden Sie einfach numpy, wenn Sie sich wirklich für die Perfektion interessieren).

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

print list(gen([4, 6, 12]))
0
gonz

Versuche dies: Die Funktion "akkumulieren" führt zusammen mit dem Operator add die laufende Addition aus.

import itertools  
import operator  
result = itertools.accumulate([1,2,3,4,5], operator.add)  
list(result)
0
Vani S
In [42]: a = [4, 6, 12]

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

Dies ist etwas schneller als die von @Ashwini angegebene Generatormethode für kleine Listen

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

Bei größeren Listen ist der Generator der richtige Weg. . . 

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
0
reptilicus

Ein reiner Python-Oneliner für kumulierte Summe: 

cumsum = lambda X: X[:1] + cumsum([X[0]+X[1]] + X[2:]) if X[1:] else X

Dies ist eine rekursive Version, die von rekursiven Summensummen inspiriert ist. Einige Erklärungen:

  1. Der erste Begriff X[:1] ist eine Liste, die das vorherige Element enthält, und ist fast identisch mit [X[0]] (die sich für leere Listen beschweren würde).
  2. Der rekursive Aufruf cumsum im zweiten Ausdruck verarbeitet das aktuelle Element [1] und die verbleibende Liste, deren Länge um eins reduziert wird.
  3. if X[1:] ist für if len(X)>1 kürzer.

Prüfung:

cumsum([4,6,12])
#[4, 10, 22]

cumsum([])
#[]

Und ähnlich für kumulative Produkte:

cumprod = lambda X: X[:1] + cumprod([X[0]*X[1]] + X[2:]) if X[1:] else X

Prüfung:

cumprod([4,6,12])
#[4, 24, 288]
0
Friedrich

Sie können die kumulative Summenliste in linearer Zeit mit einer einfachen for-Schleife berechnen:

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]

Die Standardbibliothek itertools.accumulate ist möglicherweise eine schnellere Alternative (da sie in C implementiert ist):

from itertools import accumulate
time_interval = [4, 6, 12]
print(list(accumulate(time_interval)))  # [4, 10, 22]
0
Eugene Yarmash

Ohne Numpy verwenden zu müssen, können Sie direkt über das Array laufen und die Summe auf dem Weg sammeln. Zum Beispiel:

a=range(10)
i=1
while((i>0) & (i<10)):
    a[i]=a[i-1]+a[i]
    i=i+1
print a

Ergebnisse in: 

[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
0
user3062149
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))
0
Sugandha