Anda dapat menggunakan itertools.teedan zipmembuat hasilnya secara efisien:
from itertools import tee
# python2 only:
#from itertools import izip as zip
def differences(seq):
iterable, copied = tee(seq)
next(copied)
for x, y in zip(iterable, copied):
yield y - x
Atau gunakan itertools.islicesebagai gantinya:
from itertools import islice
def differences(seq):
nexts = islice(seq, 1, None)
for x, y in zip(seq, nexts):
yield y - x
Anda juga dapat menghindari penggunaan itertoolsmodul:
def differences(seq):
iterable = iter(seq)
prev = next(iterable)
for element in iterable:
yield element - prev
prev = element
Semua solusi ini bekerja dalam ruang konstan jika Anda tidak perlu menyimpan semua hasil dan mendukung iterable tak terbatas.
Berikut beberapa tolok ukur mikro dari solusi tersebut:
In [12]: L = range(10**6)
In [13]: from collections import deque
In [15]: %timeit deque(differences_tee(L), maxlen=0)
10 loops, best of 3: 122 ms per loop
In [16]: %timeit deque(differences_islice(L), maxlen=0)
10 loops, best of 3: 127 ms per loop
In [17]: %timeit deque(differences_no_it(L), maxlen=0)
10 loops, best of 3: 89.9 ms per loop
Dan solusi lain yang diusulkan:
In [18]: %timeit [x[1] - x[0] for x in zip(L[1:], L)]
10 loops, best of 3: 163 ms per loop
In [19]: %timeit [L[i+1]-L[i] for i in range(len(L)-1)]
1 loops, best of 3: 395 ms per loop
In [20]: import numpy as np
In [21]: %timeit np.diff(L)
1 loops, best of 3: 479 ms per loop
In [35]: %%timeit
...: res = []
...: for i in range(len(L) - 1):
...: res.append(L[i+1] - L[i])
...:
1 loops, best of 3: 234 ms per loop
Perhatikan bahwa:
zip(L[1:], L)setara dengan zip(L[1:], L[:-1])karena zipsudah berakhir pada input terpendek, namun ia menghindari seluruh salinan L.
- Mengakses elemen tunggal dengan indeks sangat lambat karena setiap akses indeks adalah panggilan metode dalam python
numpy.diffadalah lambat karena harus pertama mengkonversi listke ndarray. Jelas jika Anda mulai dengan ndarrayitu akan jauh lebih cepat:
In [22]: arr = np.array(L)
In [23]: %timeit np.diff(arr)
100 loops, best of 3: 3.02 ms per loop
[abs(j-i) for i,j in zip(t, t[1:])]