Ich möchte wissen, wie man am besten (kompakter und "pythonischer") das letzte Element in einer for-Schleife speziell behandelt. Es gibt einen Code, der nur zwischen Elementen aufgerufen werden sollte und im letzten unterdrückt wird.
So mache ich das derzeit:
for i, data in enumerate(data_list):
code_that_is_done_for_every_element
if i != len(data_list) - 1:
code_that_is_done_between_elements
Gibt es einen besseren Weg?
Hinweis: Ich möchte es nicht mit Hacks wie using machen reduce
.;)
Antworten:
In den meisten Fällen ist es einfacher (und billiger), die erste Iteration anstelle der letzten zum Sonderfall zu machen :
Dies funktioniert für alle iterierbaren Elemente, auch für diejenigen, die keine haben
len()
:Abgesehen davon glaube ich nicht, dass es eine allgemein überlegene Lösung gibt, da dies davon abhängt, was Sie versuchen zu tun. Wenn Sie beispielsweise eine Zeichenfolge aus einer Liste erstellen, ist es natürlich besser, diese zu verwenden,
str.join()
als einefor
Schleife „mit Sonderfall“ zu verwenden.Nach dem gleichen Prinzip, aber kompakter:
Kommt mir bekannt vor, nicht wahr? :) :)
Für @ofko und andere, die wirklich herausfinden müssen, ob der aktuelle Wert eines iterierbaren ohne
len()
der letzte ist, müssen Sie nach vorne schauen:Dann können Sie es so verwenden:
quelle
if
hinzugefügt, die vermieden werden könnte, wenn die Schleife in zwei Schleifen aufgeteilt würde. Dies ist jedoch nur relevant, wenn eine große Datenliste iteriert wird.next()
. Dann nutze ich, dass ein Iterator für sich iterierbar ist, damit ich ihn in derfor
Schleife bis zur Erschöpfung verwenden kann, Iteration vom zweiten bis zum letzten Wert. Währenddessen behalte ich den aktuellen Wert, den ich lokal vom Iterator abgerufen habe, undyield
stattdessen den letzten. Auf diese Weise weiß ich, dass noch ein weiterer Wert zu erwarten ist. Nach der for-Schleife habe ich jeden Wert außer dem letzten gemeldet.Obwohl diese Frage ziemlich alt ist, bin ich über Google hierher gekommen und habe einen ganz einfachen Weg gefunden: List Slicing. Angenommen, Sie möchten ein '&' zwischen alle Listeneinträge setzen.
Dies gibt '1 & 2 & 3' zurück.
quelle
len(l)=1000000
in diesem Beispiel Programm wird für eine Weile laufen.append
wird afaik empfohlen.l=[1,2,3]; l.append(4);
Der 'Code zwischen' ist ein Beispiel für das Head-Tail- Muster.
Sie haben einen Artikel, auf den eine Folge von (zwischen Artikel-) Paaren folgt. Sie können dies auch als eine Folge von (Element, zwischen) Paaren gefolgt von einem Element anzeigen. Es ist im Allgemeinen einfacher, das erste Element als etwas Besonderes und alle anderen als "Standard" -Fall zu betrachten.
Um zu vermeiden, dass sich Code wiederholt, müssen Sie eine Funktion oder ein anderes Objekt bereitstellen, um den Code zu enthalten, den Sie nicht wiederholen möchten. Das Einbetten einer if- Anweisung in eine Schleife, die bis auf ein einziges Mal immer falsch ist, ist irgendwie albern.
Dies ist zuverlässiger, da es etwas einfacher zu beweisen ist. Es erstellt keine zusätzliche Datenstruktur (dh eine Kopie einer Liste) und erfordert nicht viel verschwendete Ausführung einer if- Bedingung, die nur einmal falsch ist.
quelle
if
Anweisungen, sodass das Argument "Verschwendete Ausführung" nicht gilt.if
s spart" interpretiert . Offensichtlich beziehen Sie sich nur auf "Code-Sauberkeit"?if
Anweisung von der Python-Community als sauberer angesehen?Wenn Sie nur das letzte Element in ändern
data_list
möchten, können Sie einfach die Notation verwenden:Es sieht jedoch so aus, als würden Sie mehr als das tun. Es ist nichts wirklich falsch an deinem Weg. Ich habe sogar einen kurzen Blick auf Django-Code für ihre Vorlagen-Tags geworfen und sie tun im Grunde das, was Sie tun.
quelle
if data != datalist[-1]:
ändern und alles andere gleich lassen, ist dies meiner Meinung nach der beste Weg, dies zu codieren.wenn die Artikel einzigartig sind:
andere Optionen:
quelle
Dies ähnelt dem Ansatz von Ants Aasma, jedoch ohne Verwendung des itertools-Moduls. Es ist auch ein verzögerter Iterator, der ein einzelnes Element im Iterator-Stream vorwegnimmt:
quelle
Sie können ein Schiebefenster über den Eingabedaten verwenden, um einen Blick auf den nächsten Wert zu werfen, und einen Sentinel verwenden, um den letzten Wert zu ermitteln. Dies funktioniert auf jedem iterablen Gerät, sodass Sie die Länge nicht im Voraus kennen müssen. Die paarweise Implementierung basiert auf itertools-Rezepten .
quelle
Gibt es keine Möglichkeit, alle außer dem letzten Element zu durchlaufen und das letzte außerhalb der Schleife zu behandeln? Schließlich wird eine Schleife erstellt, um etwas Ähnliches wie alle Elemente zu tun, über die Sie eine Schleife ausführen. Wenn ein Element etwas Besonderes benötigt, sollte es nicht in der Schleife sein.
(Siehe auch diese Frage: Verdient-das-letzte-Element-in-einer-Schleife-eine-separate-Behandlung )
BEARBEITEN: Da es bei der Frage eher um das "Dazwischen" geht, ist entweder das erste Element das besondere, da es keinen Vorgänger hat, oder das letzte Element ist insofern etwas Besonderes, als es keinen Nachfolger hat.
quelle
Ich mag den Ansatz von @ ethan-t, ist aber
while True
aus meiner Sicht gefährlich.Hier
data_list
ist so, dass das letzte Element wertmäßig dem ersten der Liste entspricht. L kann mit ausgetauscht werden,data_list
aber in diesem Fall ist es nach der Schleife leer.while True
kann auch verwendet werden, wenn Sie überprüfen, ob die Liste vor der Verarbeitung nicht leer ist oder die Prüfung nicht benötigt wird (autsch!).Das Gute daran ist, dass es schnell ist. Das Schlechte - es ist zerstörbar (
data_list
wird leer).Intuitivste Lösung:
Oh ja, du hast es schon vorgeschlagen!
quelle
Es ist nichts Falsches an Ihrem Weg, es sei denn, Sie haben 100 000 Schleifen und möchten 100 000 "if" -Anweisungen speichern. In diesem Fall können Sie diesen Weg gehen:
Ausgänge:
Aber wirklich, in deinem Fall fühle ich mich übertrieben.
In jedem Fall werden Sie wahrscheinlich mehr Glück beim Schneiden haben:
oder nur :
Irgendwann eine KISS-Methode, um Ihre Sachen zu erledigen, und das würde mit jedem iterablen funktionieren, auch mit denen ohne
__len__
:Ausgaben:
Wenn ich das Gefühl habe, ich würde es so machen, scheint mir das einfach zu sein.
quelle
item
anstatt es mit neu zu berechnenlist[-1]
. Aber trotzdem: Ich glaube nicht, dass das OP darum gebeten hat, oder?iterable.__iter__()
- Bitte__
Funktionen nicht direkt aufrufen . Sollte seiniter(iterable)
.Verwenden Sie Slicing und
is
, um nach dem letzten Element zu suchen:Vorsichtsmaßnahme : Dies funktioniert nur, wenn alle Elemente in der Liste tatsächlich unterschiedlich sind (unterschiedliche Speicherorte im Speicher haben). Unter der Haube kann Python gleiche Elemente erkennen und dieselben Objekte für sie wiederverwenden. Zum Beispiel für Zeichenfolgen mit demselben Wert und gemeinsamen Ganzzahlen.
quelle
Wenn Sie die Liste durchgehen, hat dies auch für mich funktioniert:
quelle
Google hat mich zu dieser alten Frage gebracht, und ich denke, ich könnte diesem Problem einen anderen Ansatz hinzufügen.
Die meisten Antworten hier würden sich mit einer ordnungsgemäßen Behandlung einer for-Schleifensteuerung befassen, wie sie gefragt wurde. Wenn die data_list jedoch zerstörbar ist, würde ich vorschlagen, dass Sie die Elemente aus der Liste entfernen, bis Sie eine leere Liste erhalten:
Sie können sogar while len (element_list) verwenden, wenn Sie mit dem letzten Element nichts tun müssen. Ich finde diese Lösung eleganter als den Umgang mit next ().
quelle
Für mich ist die einfachste und pythonischste Art, einen Sonderfall am Ende einer Liste zu behandeln, folgende:
Dies kann natürlich auch verwendet werden, um das erste Element auf besondere Weise zu behandeln.
quelle
Anstatt hochzuzählen, können Sie auch herunterzählen:
quelle
Verzögern Sie die spezielle Behandlung des letzten Elements bis nach der Schleife.
quelle
Es gibt mehrere Möglichkeiten. Das Schneiden wird am schnellsten sein. Hinzufügen einer weiteren Methode mit der Methode .index ():
quelle
Unter der Annahme, dass die Eingabe als Iterator erfolgt, können Sie Tee und izip von itertools folgendermaßen verwenden:
Demo:
quelle
Die einfachste Lösung, die mir in den Sinn kommt, ist:
Wir schauen also immer nach vorne, indem wir die Verarbeitung um eine Iteration verzögern. Um etwas während der ersten Iteration zu überspringen, fange ich einfach den Fehler ab.
Natürlich müssen Sie ein bisschen nachdenken, damit das
NameError
erhöht wird, wenn Sie es wollen.Behalten Sie auch den Rat
Dies setzt voraus, dass der Name new zuvor nicht definiert wurde. Wenn Sie paranoid sind, können Sie sicherstellen, dass
new
dies nicht existiert, indem Sie:Alternativ können Sie natürlich auch eine if-Anweisung (
if notfirst: print(new) else: notfirst = True
) verwenden. Aber soweit ich weiß, ist der Overhead größer.Daher erwarte ich, dass der Overhead nicht auswählbar ist.
quelle
Zählen Sie die Artikel einmal und halten Sie sich mit der Anzahl der verbleibenden Artikel auf dem Laufenden:
Auf diese Weise bewerten Sie die Länge der Liste nur einmal. Viele der Lösungen auf dieser Seite scheinen davon auszugehen, dass die Länge im Voraus nicht verfügbar ist, aber das ist nicht Teil Ihrer Frage. Wenn Sie die Länge haben, verwenden Sie es.
quelle
Eine einfache Lösung, die mir in den Sinn kommt, wäre:
Eine zweite ebenso einfache Lösung könnte durch Verwendung eines Zählers erreicht werden:
quelle