135 votes

Comment trouver la somme cumulée de nombres dans une liste ?

time_interval = [4, 6, 12]

Je veux résumer les chiffres comme [4, 4+6, 4+6+12] afin d'obtenir la liste t = [4, 10, 22] .

J'ai essayé ce qui suit :

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

14voto

Steven Rumbalski Points 16838

Expressions d'affectation de PEP 572 (nouveau dans Python 3.8) offrent une autre façon de résoudre ce problème :

time_interval = [4, 6, 12]

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

11voto

eugene y Points 37378

Vous pouvez calculer la liste de la somme cumulative en temps linéaire avec un simple for boucle :

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]

La bibliothèque standard itertools.accumulate peut être une alternative plus rapide (puisqu'il est implémenté en C) :

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

7voto

Viacheslav Z Points 650

Depuis python 3.8 il est possible d'utiliser Expressions d'affectation ainsi, des choses comme celles-ci sont devenues plus faciles à mettre en œuvre

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

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

produit

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

La même technique peut être appliquée pour trouver le produit cum, la moyenne, etc.

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}')

résulte en

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]

4voto

Cobry Points 1569

Si vous voulez une méthode pythonique sans que numpy ne fonctionne dans la version 2.7, voici comment je procéderais.

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

maintenant essayons-le et testons-le contre toutes les autres implémentations

import timeit, sys
L=list(range(10000))
if sys.version_info >= (3, 0):
    reduce = functools.reduce
    xrange = range

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

4voto

Aashish Chaubey Points 540

Il peut y avoir plusieurs réponses à cette question, en fonction de la longueur de la liste et de la performance. Une façon très simple à laquelle je peux penser sans penser à la performance est la suivante :

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

[1, 3, 6, 10]

Cela se fait en utilisant la compréhension de liste et cela peut fonctionner assez bien, c'est juste qu'ici j'ajoute sur le sous tableau plusieurs fois, vous pourriez éventuellement improviser sur cela et le rendre simple !

Santé à votre projet !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X