8 Stimmen

wie man sicher Elemente aus einer Liste in Python entfernt

Ich gehe in einer Schleife durch eine Liste und entferne die Elemente, die meine Bedingung erfüllen. Aber warum funktioniert das nicht, wie unten beschrieben? Ich danke Ihnen.

>>> a=[ i for i in range(4)]
>>> a
[0, 1, 2, 3]
>>> for e in a:
...     if (e > 1) and (e < 4):
...         a.remove(e)
... 
>>> a
[0, 1, 3]
>>> a=[ i for i in range(4)]
>>> for e in a:
...     if (e > -1) and (e < 3):
...         a.remove(e)
... 
>>> a
[1, 3]

11voto

Sie können etwas nicht ändern, während Sie es iterieren. Die Ergebnisse sind seltsam und kontraintuitiv und fast nie das, was Sie wollen. In vielen Sammlungen ist dies sogar ausdrücklich untersagt (z. B. bei Sets und Dicts).

Iterieren Sie stattdessen über eine Kopie ( for e in a[:]: ... ) oder, anstatt eine bestehende Liste zu ändern, diese zu filtern, um eine neue Liste mit den gewünschten Elementen zu erhalten ( [e for e in a if ...] ). Beachten Sie, dass Sie in vielen Fällen nicht erneut iterieren müssen, um zu filtern, sondern die Filterung einfach mit der Generierung der Daten zusammenführen.

6voto

Rafe Kettler Punkte 73546

Warum tun Sie dies nicht zunächst im Listenverständnis? z.B.

[i for i in range(4) if i <= 1 or i >= 4]

Sie können damit auch eine neue Liste aus der vorhandenen Liste erstellen, z. B.

[x for x in a if x <= 1 or x >= 4]

3voto

Michael Dillon Punkte 31142

Die Idee des Filterns ist gut, geht aber an der Tatsache vorbei, dass einige Listen sehr groß sein können und die Anzahl der zu entfernenden Elemente sehr klein sein kann.

In diesem Fall besteht die Antwort darin, sich die Listenindizes der zu entfernenden Elemente zu merken und dann die Liste der Indizes, sortiert vom größten zum kleinsten, durchzugehen und die Elemente zu entfernen.

3voto

Hugh Bothwell Punkte 52831

Am einfachsten lässt sich das veranschaulichen, wenn man sich vorstellt, dass die Iteration mit Listen-Offsets anstelle der eigentlichen Elemente arbeitet - man tut etwas mit dem ersten Element, dann mit dem zweiten Element, dann mit dem dritten Element, bis keine Elemente mehr vorhanden sind. Wenn Sie die Anzahl der Elemente in der Liste ändern, ändern sich auch die Offsets aller verbleibenden Elemente in der Liste:

lst = [1,2,3,4]
for item in lst:
    if item==2:
        lst.remove(item)
    else:
        print item
print lst

führt zu

1
4
[1,3,4]

was Sinn macht, wenn man es so durchgeht:

[1,2,3,4]
 ^
 first item is not 2, so print it -> 1

[1,2,3,4]
   ^
   second item is 2, so remove it

[1,3,4]
     ^
     third item is 4, so print it -> 4

Die einzige wirkliche Lösung ist die Anzahl der Elemente in der Liste nicht ändern, während Sie die Liste durchgehen . Kopieren Sie die Elemente, die Sie beibehalten möchten, in eine neue Liste, oder behalten Sie die Werte im Auge, die Sie entfernen möchten, und führen Sie das Entfernen nach Wert in einem separaten Durchgang durch.

1voto

Es ist nicht sicher, Elemente aus einer Liste zu entfernen, während sie durchlaufen wird. Dafür gibt es die Filterfunktion. Sie nimmt eine Funktion (die ein Argument zulässt) und eine Iterable (in diesem Fall Ihre Liste). Sie gibt eine neue Iterable desselben Typs (hier wieder eine Liste) mit den Elementen zurück, bei denen die auf das Element angewandte Funktion True zurückgegeben hat:

In Ihrem Fall können Sie eine Lambda-Funktion wie diese verwenden:

a = filter(lambda x: x > 1 and x < 4, range(4))

oder ob Sie die Liste bereits haben:

a = range(4)
a = filter(lambda x: x > 1 and x < 4, a)

Denken Sie daran, dass bei Verwendung von Python3 ein Iterator und keine Liste zurückgegeben wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X