Oft genug habe ich festgestellt, dass eine Liste paarweise verarbeitet werden muss. Ich habe mich gefragt, welcher pythonische und effiziente Weg dies sein würde, und habe dies bei Google gefunden:
pairs = zip(t[::2], t[1::2])
Ich dachte, das wäre pythonisch genug, aber nach einer kürzlichen Diskussion zwischen Redewendungen und Effizienz entschied ich mich, einige Tests durchzuführen:
import time
from itertools import islice, izip
def pairs_1(t):
return zip(t[::2], t[1::2])
def pairs_2(t):
return izip(t[::2], t[1::2])
def pairs_3(t):
return izip(islice(t,None,None,2), islice(t,1,None,2))
A = range(10000)
B = xrange(len(A))
def pairs_4(t):
# ignore value of t!
t = B
return izip(islice(t,None,None,2), islice(t,1,None,2))
for f in pairs_1, pairs_2, pairs_3, pairs_4:
# time the pairing
s = time.time()
for i in range(1000):
p = f(A)
t1 = time.time() - s
# time using the pairs
s = time.time()
for i in range(1000):
p = f(A)
for a, b in p:
pass
t2 = time.time() - s
print t1, t2, t2-t1
Dies waren die Ergebnisse auf meinem Computer:
1.48668909073 2.63187503815 1.14518594742
0.105381965637 1.35109519958 1.24571323395
0.00257992744446 1.46182489395 1.45924496651
0.00251388549805 1.70076990128 1.69825601578
Wenn ich sie richtig interpretiere, sollte dies bedeuten, dass die Implementierung von Listen, Listenindizierung und Listen-Slicing in Python sehr effizient ist. Es ist ein Ergebnis, das sowohl beruhigend als auch unerwartet ist.
Gibt es eine andere, "bessere" Möglichkeit, eine Liste paarweise zu durchlaufen?
Beachten Sie, dass wenn die Liste eine ungerade Anzahl von Elementen enthält, das letzte nicht in einem der Paare enthalten ist.
Welches wäre der richtige Weg, um sicherzustellen, dass alle Elemente enthalten sind?
Ich habe diese beiden Vorschläge aus den Antworten auf die Tests hinzugefügt:
def pairwise(t):
it = iter(t)
return izip(it, it)
def chunkwise(t, size=2):
it = iter(t)
return izip(*[it]*size)
Dies sind die Ergebnisse:
0.00159502029419 1.25745987892 1.25586485863
0.00222492218018 1.23795199394 1.23572707176
Ergebnisse bisher
Am pythonischsten und sehr effizientesten:
pairs = izip(t[::2], t[1::2])
Am effizientesten und sehr pythonisch:
pairs = izip(*[iter(t)]*2)
Ich brauchte einen Moment, um herauszufinden, dass die erste Antwort zwei Iteratoren verwendet, während die zweite einen einzigen verwendet.
Um Sequenzen mit einer ungeraden Anzahl von Elementen zu behandeln, wurde vorgeschlagen, die ursprüngliche Sequenz um ein Element ( None
) zu erweitern, das mit dem vorherigen letzten Element gepaart wird, was erreicht werden kann itertools.izip_longest()
.
Schließlich
Beachten Sie, dass sich Python 3.x zip()
wie folgt verhält itertools.izip()
und nicht mehr vorhanden itertools.izip()
ist.
timeit
Moduls etwas Hokuspokus verwendest .