Ich iteriere über eine Liste von Tupeln in Python und versuche, sie zu entfernen, wenn sie bestimmte Kriterien erfüllen.
for tup in somelist:
if determine(tup):
code_to_remove_tup
Was soll ich anstelle von verwenden code_to_remove_tup
? Ich kann nicht herausfinden, wie ich den Gegenstand auf diese Weise entfernen kann.
Antworten:
Mit einem Listenverständnis können Sie eine neue Liste erstellen, die nur die Elemente enthält, die Sie nicht entfernen möchten:
Durch Zuweisen zum Slice
somelist[:]
können Sie die vorhandene Liste so ändern, dass sie nur die gewünschten Elemente enthält:Dieser Ansatz kann nützlich sein, wenn andere Verweise auf vorhanden sind
somelist
, um die Änderungen widerzuspiegeln.Anstelle eines Verständnisses könnten Sie auch verwenden
itertools
. In Python 2:Oder in Python 3:
Aus Gründen der Klarheit und für diejenigen, die die Verwendung der
[:]
Notation als hackisch oder unscharf empfinden, ist hier eine explizitere Alternative. Theoretisch sollte es räumlich und zeitlich die gleiche Leistung erbringen wie die oben genannten Einzeiler.Es funktioniert auch in anderen Sprachen, die möglicherweise nicht über die Fähigkeit zum Ersetzen von Elementen in Python-Listen verfügen , mit minimalen Änderungen. Zum Beispiel werfen nicht alle Sprachen leere Listen in eine
False
wie Python. Sie könnenwhile somelist:
etwas expliziteres ersetzenwhile len(somelist) > 0:
.quelle
somelist[:] = (x for x in somelist if determine(x))
dies verwenden, wird ein Generator erstellt, der möglicherweise keine unnötigen Kopien erstellt.list_ass_slice()
Funktion, diesomelist[:]=
AufrufePySequence_Fast()
intern implementiert . Diese Funktion gibt immer eine Liste zurück, dh die Lösung von @Alex Martelli, die bereits eine Liste anstelle eines Generators verwendet, ist höchstwahrscheinlich effizientersomelist
nicht in beiden Methoden mutiert?Die Antworten, die auf ein Listenverständnis hinweisen, sind FAST korrekt - außer dass sie eine völlig neue Liste erstellen und ihr dann den gleichen Namen geben wie die alte Liste. Sie ändern NICHT die alte Liste an Ort und Stelle. Das unterscheidet sich von dem, was Sie durch selektives Entfernen tun würden, wie in @ Lennarts Vorschlag - es ist schneller, aber wenn auf Ihre Liste über mehrere Referenzen zugegriffen wird, ist die Tatsache, dass Sie nur eine der Referenzen erneut einsetzen und das Listenobjekt NICHT ändern selbst kann zu subtilen, katastrophalen Fehlern führen.
Glücklicherweise ist es extrem einfach, sowohl die Geschwindigkeit des Listenverständnisses als auch die erforderliche Semantik der direkten Änderung zu ermitteln - nur Code:
Man beachte den feinen Unterschied mit anderen Antworten: dies ist die Zuordnung nicht zu einem barename - es zu einer Liste Slice zuweisen, nur die gesamte Liste sein geschieht, wodurch die Liste ersetzt Inhalte innerhalb des gleichen Objekts Python - Liste , anstatt nur erneuten Einsetzen eine Referenz (vom vorherigen Listenobjekt zum neuen Listenobjekt) wie die anderen Antworten.
quelle
a
durch den Inhalt von dict ersetzen möchtenb
, verwenden Siea.clear(); a.update(b)
.x = ['foo','bar','baz']; y = x; x = [item for item in x if determine(item)];
Dies wirdx
dem Ergebnis des Listenverständnisses neu zugewiesen ,y
bezieht sich jedoch weiterhin auf die ursprüngliche Liste['foo','bar','baz']
. Wenn Sie erwartet habenx
undy
auf dieselbe Liste verweisen möchten, haben Sie möglicherweise Fehler eingeführt. Sie verhindern dies, indem Sie einem Teil der gesamten Liste zuweisen, wie Alex zeigt, und ich zeige hier :x = ["foo","bar","baz"]; y = x; x[:] = [item for item in x if determine(item)];
. Die Liste wird an Ort und Stelle geändert. Stellen Sie sicher, dass alle Verweise auf die Liste (sowohlx
als auchy
hier) auf die neue Liste verweisen.filter
Funktion verwenden, wird eine neue Liste erstellt, und es werden keine Elemente an Ort und Stelleolist[:] = [i for i in olist if not dislike(i)]
Sie müssen eine Kopie der Liste erstellen und diese zuerst durchlaufen, da sonst die Iteration mit möglicherweise unerwarteten Ergebnissen fehlschlägt.
Zum Beispiel (hängt von der Art der Liste ab):
Ein Beispiel:
quelle
list(somelist)
konvertiert eine iterable in eine Liste.somelist[:]
Erstellt eine Kopie eines Objekts, das das Schneiden unterstützt. Sie machen also nicht unbedingt dasselbe. In diesem Fall möchte ich eine Kopie dessomelist
Objekts[:]
remove()
muss die GANZE Liste für jede Iteration durchgehen, damit es ewig dauert.Du musst rückwärts gehen, sonst ist es ein bisschen so, als würdest du den Ast absägen, auf dem du sitzt :-)
Python 2-Benutzer: Ersetzen
range
durchxrange
, um das Erstellen einer fest codierten Liste zu vermeidenquelle
reversed()
builtinenumerate
gibt einen Iterator zurück undreversed
erwartet eine Sequenz. Ich denke, Sie könnten es tun,reversed(list(enumerate(somelist)))
wenn es Ihnen nichts ausmacht, eine zusätzliche Liste im Speicher zu erstellen.m
mal langsamer sein.Offizielles Python 2-Tutorial 4.2. "für Aussagen"
https://docs.python.org/2/tutorial/controlflow.html#for-statements
Dieser Teil der Dokumentation macht deutlich, dass:
[:]
Python 2-Dokumentation 7.3. "Die for-Anweisung"
https://docs.python.org/2/reference/compound_stmts.html#for
In diesem Teil der Dokumentation wird erneut angegeben, dass Sie eine Kopie erstellen müssen, und es wird ein Beispiel für das tatsächliche Entfernen angegeben:
Ich bin jedoch mit dieser Implementierung nicht einverstanden, da
.remove()
die gesamte Liste iteriert werden muss , um den Wert zu finden.Beste Problemumgehungen
Entweder:
Starten Sie ein neues Array von Grund
.append()
auf neu und am Ende zurück: https://stackoverflow.com/a/1207460/895245Diesmal zeiteffizient, aber weniger platzsparend, da während der Iteration eine Kopie des Arrays aufbewahrt wird.
Verwendung
del
mit einem Index: https://stackoverflow.com/a/1207485/895245Dies ist platzsparender, da die Array-Kopie ausgegeben wird, aber weniger zeiteffizient, da CPython-Listen mit dynamischen Arrays implementiert werden .
Dies bedeutet, dass zum Entfernen von Elementen alle folgenden Elemente um eins zurück verschoben werden müssen, was O (N) ist.
Im Allgemeinen möchten Sie nur schneller fahren
.append()
standardmäßig Option wählen, es sei denn, der Speicher ist ein großes Problem.Könnte Python das besser machen?
Es scheint, dass diese spezielle Python-API verbessert werden könnte. Vergleichen Sie es zum Beispiel mit:
std::vector::erase
das dem Element nach dem Entfernen einen gültigen Interator zurückgibtBeides macht deutlich, dass Sie eine iterierte Liste nur mit dem Iterator selbst ändern können, und bietet Ihnen effiziente Möglichkeiten, dies zu tun, ohne die Liste zu kopieren.
Möglicherweise liegt der Grund dafür darin, dass angenommen wird, dass Python-Listen von dynamischen Arrays unterstützt werden, und daher ist jede Art der Entfernung ohnehin zeitlich ineffizient, während Java eine schönere Schnittstellenhierarchie mit beiden
ArrayList
undLinkedList
Implementierungen von hatListIterator
.Es scheint auch keinen expliziten verknüpften Listentyp in der Python stdlib zu geben: Python Linked List
quelle
Ihr bester Ansatz für ein solches Beispiel wäre ein Listenverständnis
In Fällen, in denen Sie etwas Komplexeres tun als eine
determine
Funktion aufzurufen , ziehe ich es vor, eine neue Liste zu erstellen und sie einfach an sie anzuhängen. Zum BeispielWenn Sie die Liste mit
remove
kopieren, sieht Ihr Code möglicherweise etwas sauberer aus, wie in einer der folgenden Antworten beschrieben. Sie sollten dies definitiv nicht für extrem große Listen tun, da dies zuerst das Kopieren der gesamten Liste und das Ausführen einerO(n)
remove
Operation für jedes zu entfernende Element umfasst, wodurch dies zu einemO(n^2)
Algorithmus wird.quelle
Für diejenigen, die funktionale Programmierung mögen:
oder
quelle
filter
und pythonischer. 2. Wenn Sie einlambda
verwendenmap
oderfilter
die Liste comp oder genexpr, ist immer die bessere Option;map
undfilter
kann etwas schneller sein, wenn die Transformations- / Prädikatfunktion ein in C integriertes Python ist und die Iterierbarkeit nicht trivial klein ist, aber sie sind immer langsamer, wenn Sie eine benötigenlambda
, die listcomp / genexpr vermeiden könnte.Ich musste dies mit einer riesigen Liste tun, und das Duplizieren der Liste schien teuer zu sein, zumal in meinem Fall die Anzahl der Löschungen im Vergleich zu den verbleibenden Elementen gering war. Ich habe diesen Low-Level-Ansatz gewählt.
Was ich nicht weiß, ist, wie effizient ein paar Löschvorgänge im Vergleich zum Kopieren einer großen Liste sind. Bitte kommentieren Sie, wenn Sie einen Einblick haben.
quelle
list
als Datenstruktur sollte jedoch sorgfältig abgewogen werden, da das Entfernen aus der Mitte einer Liste in der Länge der Liste eine lineare Zeit in Anspruch nimmt. Wenn Sie keinen zufälligen Zugriff auf das k-te sequentielle Element benötigen, ziehen Sie vielleicht in BetrachtOrderedDict
?newlist = []
, und dannnewlist.append(array[i])
kurz zuvordel array[i]
?list()
es sich um eine verknüpfte Liste handelt, ist der Direktzugriff teuer. Wennlist()
es sich um ein Array handelt, sind die Löschvorgänge teuer, da alle folgenden Elemente vorwärts verschoben werden müssen. Ein anständiger Iterator könnte die Implementierung einer verknüpften Liste verbessern. Dies könnte jedoch platzsparend sein.Es kann sinnvoll sein, auch nur eine neue Liste zu erstellen, wenn das aktuelle Listenelement die gewünschten Kriterien erfüllt.
damit:
und um zu vermeiden, dass das gesamte Projekt mit dem neuen Listennamen neu codiert werden muss:
Hinweis aus der Python-Dokumentation:
quelle
Diese Antwort wurde ursprünglich als Antwort auf eine Frage geschrieben, die inzwischen als doppelt markiert wurde: Entfernen von Koordinaten aus der Liste in Python
Ihr Code enthält zwei Probleme:
1) Wenn Sie remove () verwenden, versuchen Sie, Ganzzahlen zu entfernen, während Sie ein Tupel entfernen müssen.
2) Die for-Schleife überspringt Elemente in Ihrer Liste.
Lassen Sie uns durchgehen, was passiert, wenn wir Ihren Code ausführen:
Das erste Problem ist, dass Sie sowohl 'a' als auch 'b' an remove () übergeben, remove () jedoch nur ein einziges Argument akzeptiert. Wie können wir remove () dazu bringen, ordnungsgemäß mit Ihrer Liste zu arbeiten? Wir müssen herausfinden, was jedes Element Ihrer Liste ist. In diesem Fall ist jedes ein Tupel. Um dies zu sehen, greifen wir auf ein Element der Liste zu (die Indizierung beginnt bei 0):
Aha! Jedes Element von L1 ist tatsächlich ein Tupel. Das ist es, was wir übergeben müssen, um () zu entfernen. Tupel in Python sind sehr einfach. Sie werden einfach durch Einfügen von Werten in Klammern erstellt. "a, b" ist kein Tupel, aber "(a, b)" ist ein Tupel. Also ändern wir Ihren Code und führen ihn erneut aus:
Dieser Code läuft fehlerfrei, aber schauen wir uns die Liste an, die er ausgibt:
Warum ist (1, -2) noch in Ihrer Liste? Es stellt sich heraus, dass das Ändern der Liste während der Verwendung einer Schleife zum Durchlaufen eine sehr schlechte Idee ist, ohne besondere Sorgfalt. Der Grund dafür, dass (1, -2) in der Liste verbleibt, besteht darin, dass sich die Positionen der einzelnen Elemente in der Liste zwischen den Iterationen der for-Schleife geändert haben. Schauen wir uns an, was passiert, wenn wir dem obigen Code eine längere Liste hinzufügen:
Wie Sie aus diesem Ergebnis schließen können, überspringt die nächste Iteration der Schleife jedes Mal, wenn die bedingte Anweisung als wahr ausgewertet und ein Listenelement entfernt wird, die Auswertung des nächsten Elements in der Liste, da sich seine Werte jetzt an verschiedenen Indizes befinden.
Die intuitivste Lösung besteht darin, die Liste zu kopieren, dann die ursprüngliche Liste zu durchlaufen und nur die Kopie zu ändern. Sie können dies folgendermaßen versuchen:
Die Ausgabe ist jedoch identisch mit zuvor:
Dies liegt daran, dass Python beim Erstellen von L2 kein neues Objekt erstellt hat. Stattdessen wurde L2 lediglich auf dasselbe Objekt wie L1 bezogen. Wir können dies mit 'is' überprüfen, das sich von lediglich "equals" (==) unterscheidet.
Mit copy.copy () können wir eine echte Kopie erstellen. Dann funktioniert alles wie erwartet:
Schließlich gibt es eine sauberere Lösung, als eine völlig neue Kopie von L1 erstellen zu müssen. Die Funktion reverse ():
Leider kann ich nicht ausreichend beschreiben, wie reverse () funktioniert. Es gibt ein 'listreverseiterator'-Objekt zurück, wenn eine Liste an dieses übergeben wird. Aus praktischen Gründen können Sie sich vorstellen, dass eine umgekehrte Kopie des Arguments erstellt wird. Dies ist die Lösung, die ich empfehle.
quelle
Wenn Sie während der Iteration etwas anderes tun möchten, ist es möglicherweise hilfreich, sowohl den Index (der garantiert, dass Sie darauf verweisen können, z. B. wenn Sie eine Liste von Diktaten haben) als auch den tatsächlichen Inhalt des Listenelements abzurufen.
enumerate
Ermöglicht den gleichzeitigen Zugriff auf das Element und den Index.reversed
ist so, dass sich die Indizes, die Sie später löschen werden, nicht auf Sie ändern.quelle
Vielleicht möchten Sie verwenden
filter()
verfügbar als integrierte Funktion verwenden.Weitere Details finden Sie hier
quelle
Die meisten Antworten hier möchten, dass Sie eine Kopie der Liste erstellen. Ich hatte einen Anwendungsfall, in dem die Liste ziemlich lang war (110.000 Elemente) und es klüger war, die Liste stattdessen weiter zu reduzieren.
Zunächst einmal müssen Sie foreach - Schleife mit while - Schleife ersetzen ,
Der Wert von
i
wird im if-Block nicht geändert, da Sie den Wert des neuen Elements aus demselben Index abrufen möchten, sobald das alte Element gelöscht wurde.quelle
Sie können das For-Looping in umgekehrter Reihenfolge versuchen, damit Sie für some_list Folgendes tun:
Auf diese Weise wird der Index ausgerichtet und leidet nicht unter den Listenaktualisierungen (unabhängig davon, ob Sie das aktuelle Element einfügen oder nicht).
quelle
reversed(list(enumerate(some_list)))
wäre einfacher, als die Indizes selbst zu berechnen.Eine mögliche Lösung, die nützlich ist, wenn Sie nicht nur einige Dinge entfernen, sondern auch mit allen Elementen in einer einzigen Schleife etwas tun möchten:
quelle
bad
Dinge entfernen , etwas damit machen und auch etwas mitgood
Dingen in einer Schleife machen möchte ?alist[:]
erstellen ( ). Und da Sie vielleicht etwas Besonderes tun, hat es tatsächlich einen Anwendungsfall. Gute Überarbeitung ist gut. Nimm meine Gegenstimme.Ich musste etwas Ähnliches tun, und in meinem Fall war das Problem der Speicher - ich musste mehrere Datensatzobjekte in einer Liste zusammenführen, nachdem ich einige Dinge mit ihnen als neues Objekt erledigt hatte, und jeden Eintrag, mit dem ich zusammengeführt wurde, entfernen Vermeiden Sie es, alle zu duplizieren und Speicher zu sprengen. In meinem Fall hat es gut funktioniert, die Objekte in einem Wörterbuch anstelle einer Liste zu haben:
`` `
`` `
quelle
TLDR:
Ich habe eine Bibliothek geschrieben, mit der Sie dies tun können:
Es ist am besten, wenn möglich eine andere Methode zu verwenden, bei der Sie Ihre Iterierbarkeit nicht ändern müssen, während Sie darüber iterieren. Bei einigen Algorithmen ist dies jedoch möglicherweise nicht so einfach. Wenn Sie also sicher sind, dass Sie das in der ursprünglichen Frage beschriebene Codemuster wirklich möchten, ist dies möglich.
Sollte auf allen veränderlichen Sequenzen funktionieren, nicht nur auf Listen.
Vollständige Antwort:
Bearbeiten: Das letzte Codebeispiel in dieser Antwort gibt einen Anwendungsfall dafür, warum Sie manchmal eine Liste an Ort und Stelle ändern möchten, anstatt ein Listenverständnis zu verwenden. Der erste Teil der Antworten dient als Tutorial, wie ein Array an Ort und Stelle geändert werden kann.
Daraus folgt die Lösung Antwort (für eine verwandte Frage) von senderle. Dies erklärt, wie der Array-Index aktualisiert wird, während eine geänderte Liste durchlaufen wird. Die folgende Lösung dient dazu, den Array-Index auch dann korrekt zu verfolgen, wenn die Liste geändert wird.
Download
fluidIter.py
von hierhttps://github.com/alanbacon/FluidIterator
, es ist nur eine einzelne Datei, so dass git nicht installiert werden muss. Es gibt kein Installationsprogramm, daher müssen Sie sicherstellen, dass sich die Datei selbst im Python-Pfad befindet. Der Code wurde für Python 3 geschrieben und ist auf Python 2 nicht getestet.Dies erzeugt die folgende Ausgabe:
Oben haben wir die
pop
Methode für das Fluidlistenobjekt verwendet. Andere häufige iterable Verfahren sind auch wie implementiertdel fluidL[i]
,.remove
,.insert
,.append
,.extend
. Die Liste kann auch mit Slices (sort
und) geändert werdenreverse
Methoden sind nicht implementiert).Die einzige Bedingung ist, dass Sie die Liste nur dann ändern müssen, wenn der Code zu irgendeinem Zeitpunkt
fluidL
oder wennl
er einem anderen Listenobjekt zugewiesen wurde, nicht funktioniert. Das ursprünglichefluidL
Objekt wird weiterhin von der for-Schleife verwendet, kann jedoch nicht mehr geändert werden.dh
Wenn wir auf den aktuellen Indexwert der Liste zugreifen möchten, können wir keine Aufzählung verwenden, da dies nur zählt, wie oft die for-Schleife ausgeführt wurde. Stattdessen verwenden wir das Iteratorobjekt direkt.
Dies gibt Folgendes aus:
Die
FluidIterable
Klasse stellt lediglich einen Wrapper für das ursprüngliche Listenobjekt bereit. Auf das ursprüngliche Objekt kann als Eigenschaft des flüssigen Objekts wie folgt zugegriffen werden:Weitere Beispiele / Tests finden Sie im
if __name__ is "__main__":
Abschnitt untenfluidIter.py
. Diese sind einen Blick wert, weil sie erklären, was in verschiedenen Situationen passiert. Beispiel: Ersetzen eines großen Teils der Liste mithilfe eines Slice. Oder Sie verwenden (und ändern) dasselbe iterable in verschachtelten for-Schleifen.Wie ich bereits sagte: Dies ist eine komplizierte Lösung, die die Lesbarkeit Ihres Codes beeinträchtigt und das Debuggen erschwert. Daher sollten zuerst andere Lösungen wie das in David Raznicks Antwort erwähnte Listenverständnis in Betracht gezogen werden. Abgesehen davon habe ich Zeiten gefunden, in denen diese Klasse für mich nützlich und einfacher zu verwenden war, als die Indizes der Elemente zu verfolgen, die gelöscht werden müssen.
Bearbeiten: Wie in den Kommentaren erwähnt, stellt diese Antwort kein Problem dar, für das dieser Ansatz eine Lösung bietet. Ich werde versuchen, das hier anzusprechen:
Listenverständnisse bieten eine Möglichkeit, eine neue Liste zu erstellen. Bei diesen Ansätzen wird jedoch jedes Element isoliert betrachtet und nicht der aktuelle Status der Liste als Ganzes.
dh
Was aber, wenn das Ergebnis von den
testFunc
Elementen abhängt, die bereits hinzugefügt wurdennewList
? Oder die Elemente noch inoldList
könnten die noch darin enthaltenen als nächstes hinzugefügt werden? Es gibt zwar immer noch eine Möglichkeit, ein Listenverständnis zu verwenden, aber es verliert allmählich seine Eleganz, und für mich ist es einfacher, eine Liste an Ort und Stelle zu ändern.Der folgende Code ist ein Beispiel für einen Algorithmus, der unter dem oben genannten Problem leidet. Der Algorithmus reduziert eine Liste so, dass kein Element ein Vielfaches eines anderen Elements ist.
Die Ausgabe und die endgültige reduzierte Liste werden unten angezeigt
quelle
some_list[:] = [x for x in some_list if not some_condition(x)]
nicht erreicht wird? Warum sollte jemand ohne eine Antwort darauf glauben, dass das Herunterladen und Verwenden Ihrer 600-Zeilen-Bibliothek mit Tippfehlern und auskommentiertem Code eine bessere Lösung für sein Problem darstellt als der Einzeiler? -1.some_list[:] = [x for x in some_list if not some_condition(y)]
woy
ein anderes Listenelement ausx
. Es wäre auch nicht möglich zu schreibensome_list[:] = [x for x in some_list if not some_condition(intermediateStateOf_some_list)]
.Die effektivste Methode ist das Listenverständnis, viele Leute zeigen ihren Fall, natürlich ist es auch ein guter Weg, um
iterator
durchzukommenfilter
.Es gibt ein Beispiel (erhalten Sie die Gewinnchancen im Tupel):
Achtung: Sie können auch nicht mit Iteratoren umgehen. Iteratoren sind manchmal besser als Sequenzen.
quelle
Die for-Schleife wird durch den Index iteriert.
Betrachten Sie eine Liste,
Sie haben die Listenvariable aufgerufen
lis
. und Sie verwenden das gleiche, um zu entfernen ..Ihre Variable
während der 5. Iteration,
Ihre Nummer 35 war keine Primzahl, also haben Sie sie von einer Liste entfernt.
und dann geht der nächste Wert (65) zum vorherigen Index über.
Der Zeiger für die 4. Iteration wurde auf den 5. verschoben.
Aus diesem Grund deckt Ihre Schleife 65 nicht ab, da sie in den vorherigen Index verschoben wurde.
Sie sollten die Liste daher nicht in eine andere Variable verweisen, die weiterhin auf das Original anstatt auf die Kopie verweist.
Kopieren Sie die Liste mit
list[::]
jetzt wirst du es geben,
Das Problem ist, dass Sie während der Iteration einen Wert aus einer Liste entfernt haben und Ihr Listenindex dann zusammenbricht.
Sie können stattdessen versuchen, das Verständnis zu verbessern.
welches alle iterierbaren wie, Liste, Tupel, Diktat, Zeichenfolge usw. unterstützt
quelle
Wenn Sie während der Iteration Elemente aus einer Liste löschen möchten, verwenden Sie eine while-Schleife, damit Sie den aktuellen Index und den Endindex nach jedem Löschen ändern können.
Beispiel:
quelle
Die anderen Antworten sind richtig, dass es normalerweise eine schlechte Idee ist, aus einer Liste zu löschen, die Sie iterieren. Durch die umgekehrte Iteration werden die Fallstricke vermieden, aber es ist viel schwieriger, dem Code zu folgen, der dies tut. Daher ist es normalerweise besser, ein Listenverständnis zu verwenden oder
filter
.Es gibt jedoch einen Fall, in dem es sicher ist, Elemente aus einer Sequenz zu entfernen, die Sie iterieren: Wenn Sie nur ein Element entfernen, während Sie iterieren. Dies kann mit a
return
oder a sichergestellt werdenbreak
. Zum Beispiel:Dies ist oft einfacher zu verstehen als ein Listenverständnis, wenn Sie einige Vorgänge mit Nebenwirkungen auf das erste Element in einer Liste ausführen, die eine bestimmte Bedingung erfüllen, und dieses Element unmittelbar danach aus der Liste entfernen.
quelle
Ich kann mir drei Ansätze vorstellen, um Ihr Problem zu lösen. Als Beispiel werde ich eine zufällige Liste von Tupeln erstellen
somelist = [(1,2,3), (4,5,6), (3,6,6), (7,8,9), (15,0,0), (10,11,12)]
. Die Bedingung, die ich wähle, istsum of elements of a tuple = 15
. In der endgültigen Liste haben wir nur die Tupel, deren Summe nicht gleich 15 ist.Was ich ausgewählt habe, ist ein zufällig ausgewähltes Beispiel. Fühlen Sie sich frei, die Liste der Tupel und die von mir gewählte Bedingung zu ändern .
Methode 1.> Verwenden Sie das von Ihnen vorgeschlagene Framework (wobei ein Code in eine for-Schleife eingefügt wird). Ich verwende einen kleinen Code mit
del
, um ein Tupel zu löschen, das diese Bedingung erfüllt. Bei diesem Verfahren fehlt jedoch ein Tupel (das die genannte Bedingung erfüllt), wenn zwei nacheinander platzierte Tupel die gegebene Bedingung erfüllen.Methode 2.> Erstellen Sie eine neue Liste, die Elemente (Tupel) enthält, bei denen die angegebene Bedingung nicht erfüllt ist (dies entspricht dem Entfernen von Listenelementen, bei denen die angegebene Bedingung erfüllt ist). Es folgt der Code dafür:
Methode 3.> Suchen Sie nach Indizes, bei denen die angegebene Bedingung erfüllt ist, und verwenden Sie dann Elemente entfernen (Tupel), die diesen Indizes entsprechen. Es folgt der Code dafür.
Methode 1 und Methode 2 sind schneller als Methode 3 . Methode2 und Methode3 sind effizienter als Methode1. Ich bevorzuge Methode2 . Für das vorgenannte Beispiel
time(method1) : time(method2) : time(method3) = 1 : 1 : 1.7
quelle
Für alles, was das Potenzial hat, wirklich groß zu sein, verwende ich Folgendes.
Das sollte deutlich schneller sein als alles andere.
quelle
In einigen Situationen, in denen Sie mehr tun, als nur eine Liste einzeln zu filtern, soll sich Ihre Iteration während der Iteration ändern.
Hier ist ein Beispiel, in dem das vorherige Kopieren der Liste falsch ist, eine umgekehrte Iteration nicht möglich ist und ein Listenverständnis ebenfalls keine Option ist.
quelle
Wenn Sie die neue Liste später verwenden, können Sie das Element einfach auf Keine setzen und es dann in der späteren Schleife wie folgt beurteilen
Auf diese Weise müssen Sie die Liste nicht kopieren und es ist einfacher zu verstehen.
quelle
Wenn Sie eine Liste mit Zahlen erstellen, möchten Sie alle Nein entfernen, die durch 3 teilbar sind.
Mit
list comprehension
wird eine neue Liste erstellt und neuer Speicherplatz erstelltMit der
lambda filter
Funktion wird eine neue Liste erstellt und Speicherplatz belegtohne Speicherplatz für neue Liste zu verbrauchen und vorhandene Liste zu ändern
quelle