Donné a = [1, 2, 3, 4, 5]
Après l'encodage, a '= [1, 1, 1, 1, 1] code >, chaque élément représente la différence par rapport à son élément précédent.
Je sais que cela peut être fait avec
for i in range(len(a) - 1, 0, -1): a[i] = a[i] - a[i - 1]
Y a-t-il un moyen plus rapide? Je travaille avec 2 milliards de chiffres ici, le processus prend environ 30 minutes.
3 Réponses :
Vous pouvez utiliser numpy.diff , par exemple :
import numpy as np a = [1, 2, 3, 4, 5] npa = np.array(a) a_diff = np.diff(npa)
Vous pouvez utiliser zip
pour rassembler la liste avec une version offset et soustraire ces valeurs
a = [a[0], *[nxt - cur for cur, nxt in zip(a, islice(a, 1, None))]]
Résultat:
[1, 1, 1, 1, 1]
AFAIK, a [1:]
créera une nouvelle liste, ce qui peut entraîner une surcharge importante si la liste d'origine est très grande. J'ai testé votre code avec islice
et il devient aussi rapide que l'approche starmap
.
Intéressant, vous avez raison, cela améliore considérablement les choses. j'aime ce type de questions - vous apprenez tellement ...
Je l'aime aussi; cela vous fait vraiment fouiller dans les codes XD.
Une manière en utilisant itertools.starmap
, islice
et operator.sub
:
l = list(range(1, 100000000)) # OP's method %timeit [l[i] - l[i - 1] for i in range(len(l) - 1, 0, -1)] # 14.2 s ± 373 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) # numpy approach by @ynotzort %timeit np.diff(l) # 8.52 s ± 301 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) # zip approach by @Nick %timeit [nxt - cur for cur, nxt in zip(l, l[1:])] # 7.96 s ± 243 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) # itertool and operator approach by @Chris %timeit [l[0], *starmap(sub, zip(islice(l, 1, None), l))] # 6.4 s ± 255 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Résultat:
[1, 1, 1, ..., 1]
Benchmark :
from operator import sub from itertools import starmap, islice l = list(range(1, 10000000)) [l[0], *starmap(sub, zip(islice(l, 1, None), l))]
C'est environ 40% plus rapide que le code numpy
et zip
à 20 millions de valeurs ... (voir ma note sur l'analyse comparative)
Il est intéressant que vos résultats montrent que mon code surpasse @ynotzort. Je me demande si cela est lié à la quantité de mémoire sur chaque machine.
@Nick Avez-vous inclus la création de la liste en tant que partie de tableau numpy ( np.array (l)
)?
Je l'ai inclus dans la configuration pour qu'il ne s'exécute qu'une seule fois.
@Nick Pour la partie numpy
, convertir une liste en numpy.ndarray
prend plus de temps que de faire le diff, et j'ai pensé que ce serait une comparaison juste d'inclure cette conversion dans le timeit . C'est peut-être là que la différence a été faite.
C'est raisonnable; si les données originales sont dans une liste, vous devrez payer ce prix pour faire le diff
. Je n'avais pas réalisé que c'était si cher non plus.