J'ai une liste [0, 1, 2, 3, 4, 5, 6] et je additionne ses parties pour que:
l = [0, 1, 2, 3, 4, 5, 6] -> 21 l = [1, 2, 3, 4, 5, 6] -> 21 l = [2, 3, 4, 5, 6] -> 20 l = [3, 4, 5, 6] -> 18 l = [4, 5, 6] -> 15 l = [5, 6] -> 11 l = [6] -> 6 l = [] -> 0
Donc, J'obtiens les sommes correspondantes des parties de la liste: [21, 21, 20, 18, 15, 11, 6, 0]
Le code que j'utilise est: p >
[somme (l [i:]) pour i dans la plage (len (l) + 1)]
Mais, pour les listes avec une plage supérieure à 100000 le code ralentit considérablement.
Une idée pourquoi et comment l'optimiser?
3 Réponses :
Pour autant que je sache, il n'y a pas de moyen propre de le faire avec des compréhensions de liste.
Ce code fonctionnera sans aucune autre bibliothèque:
[(x, total := total + x) for x in items]
À partir de Python 3.8 sur, il y a un nouvel opérateur qui pourrait aider:
def cumulative_sum(a):
total= 0
for item in a:
total += item
yield total
list(cumulative_sum(listname))
C'est l'opérateur du morse!
Je suggérerais itertools.accumulate pour cela (que je rappelle est plus rapide que np.cumsum ), avec une liste inversée pour obtenir la sortie souhaitée:
>>> from itertools import accumulate >>> lst = [0, 1, 2, 3, 4, 5, 6] >>> list(accumulate(reversed(lst)))[::-1] [21, 21, 20, 18, 15, 11, 6]
(vous pouvez facilement ajouter 0 à la fin si nécessaire )
Cela peut aider à réduire le temps de calcul pour les grandes listes:
from timeit import timeit
def sum10(l):
from itertools import accumulate
return list(accumulate(reversed(l)))[::-1]+[0]
def sum11(l):
from itertools import accumulate
return list(accumulate(l[::-1]))[::-1]+[0]
def sum20(l):
from numpy import cumsum
return list(cumsum(l[::-1]))[::-1]+[0]
def sum21(l):
from numpy import cumsum
return list(cumsum(list(reversed(l))))[::-1]+[0]
l = list(range(1000000))
iter_0 = timeit(lambda: sum10(l), number=10) #0.14102990700121154
iter_1 = timeit(lambda: sum11(l), number=10) #0.1336850459993002
nump_0 = timeit(lambda: sum20(l), number=10) #0.6019859320003889
nump_1 = timeit(lambda: sum21(l), number=10) #0.3818727100006072
Sortie :
[21, 21, 20, 18, 15, 11, 6, 0]
Ici est une comparaison des performances pour quatre méthodes différentes, qui font toutes la même chose:
l = [0, 1, 2, 3, 4, 5, 6] output = list(np.cumsum(l[::-1]))[::-1]+[0]
+ l [0] n'est pas la bonne chose à faire ici, je pense qu'ils signifient +0 toujours même si la liste ne commence pas par 0
De plus, je ne peux pas du tout reproduire vos horaires sur ipython pastebin.com/x3U1q0nZ
vous réutilisez des valeurs précalculées. Je vous suggère d'utiliser la somme cumulative
Chaque fois que vous calculez une nouvelle somme - alors que les sommes se chevauchent. Comptez à partir du dernier élément, manuellement ou en utilisant la somme cumulée de la liste.
np.cumsum.