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 .Antworten:
Meine Lieblingsmethode:
Wenn Sie alle Elemente koppeln möchten, benötigen Sie möglicherweise einen Füllwert:
quelle
itertools
Abschnitt Rezepte.izip(*[iter(t)]*size)
Ich würde sagen, dass Ihre ursprüngliche Lösung
pairs = zip(t[::2], t[1::2])
die beste ist, weil sie am einfachsten zu lesen ist (und in Python 3zip
automatisch einen Iterator anstelle einer Liste zurückgibt).Um sicherzustellen, dass alle Elemente enthalten sind, können Sie die Liste einfach um erweitern
None
.Wenn die Liste dann eine ungerade Anzahl von Elementen enthält, ist das letzte Paar
(item, None)
.quelle
Ich beginne mit einem kleinen Haftungsausschluss - verwenden Sie nicht den folgenden Code. Es ist überhaupt nicht pythonisch, ich habe nur zum Spaß geschrieben. Es ähnelt der @ THC4k-
pairwise
Funktion, verwendetiter
und schließt sie jedochlambda
. Es verwendet keinitertools
Modul und unterstützt nichtfillvalue
. Ich habe es hierher gebracht, weil es jemand interessant finden könnte:quelle
Was die meisten Pythons angeht, würde ich sagen, dass die Rezepte in den Python-Quelldokumenten (von denen einige den Antworten von @JochenRitzel sehr ähnlich sehen) wahrscheinlich die beste Wahl sind;)
quelle
Ich kann nicht sicher sagen, aber ich bezweifle es: Jede andere Durchquerung würde mehr Python-Code enthalten, der interpretiert werden muss. Die eingebauten Funktionen wie zip () sind in C geschrieben, was viel schneller ist.
Überprüfen Sie die Länge der Liste und
len(list) & 1 == 1
kopieren Sie die Liste, wenn sie ungerade ist ( ), und fügen Sie ein Element hinzu.quelle
quelle
Mach es nur:
quelle
list(zip(l, l[1:]))
und teilt die Liste nicht in Paare auf.Hier ist ein Beispiel für die Erstellung von Paaren / Beinen mithilfe eines Generators. Generatoren sind frei von Stapelbeschränkungen
Beispiel:
Ausgabe:
quelle
[(0, 1), (2, 3), (4, 5)....
zip()
gibt bereits einen Generator in Python 3.x zurück, @VladBezdenNur für den Fall, dass jemand die Antwort algorithmisch benötigt, hier ist sie:
Beachten Sie jedoch, dass Ihre ursprüngliche Liste auch auf das letzte Element reduziert wird, da Sie sie verwendet
pop
haben.quelle