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
.