2009-09-20 12 views
12

ich eine Liste haben L.löschen, indem Sie viele Elemente der Liste (Python)

I i Element löschen:

del L[i] 

Aber was, wenn ich einen Satz von nicht zusammenhängenden Indizes zu löschen?

I=set([i1, i2, i3,...]) 

tun:

for i in I: 
    del L[i] 

wird nicht funktionieren.

Irgendwelche Ideen?

+1

dupe http://stackoverflow.com/questions/497426/deleting-multiple-elements-from-a-list – SilentGhost

Antwort

31

Eine Minute please, Ich hap Eine kleine Problemo avec this Religione. - Eddie Izzard (seinen Eindruck von Martin Luther zu tun)

Löschen von Reverse-Iteration über eine Liste den Iterator zu erhalten ist eine gemeinsame Lösung für dieses Problem. Eine andere Lösung besteht darin, dies in ein anderes Problem zu verwandeln. Anstatt Elemente aus der Liste mit bestimmten Kriterien zu löschen (in Ihrem Fall existiert der Index in einer Liste von zu löschenden Indizes), erstellen Sie eine neue Liste, in der die fehlerhaften Elemente nicht vorhanden sind.

L[:] = [ item for i,item in enumerate(L) if i not in I ] 

Für diese Angelegenheit, wo Sie mit dem Indizes in I an erster Stelle kommen haben? Sie könnten die Logik kombinieren, um die Indizes zu entfernen und die neue Liste zu erstellen. Unter der Annahme, dies ist eine Liste von Objekten, und Sie wollen nur diejenigen halten, die einen isValid Test bestehen:

L[:] = [ item for item in L if item.isValid() ] 

Das ist viel einfacher als:

I = set() 
for i in range(len(L)): 
    if not L[i].isValid(): 
     I.add(i) 

for i in sorted(I, reverse=True): 
    del L[i] 

Zum größten Teil, schalte ich jede Frage über "Wie man aus einer Liste die Elemente löscht, die ich nicht möchte" in "wie man eine neue Liste erstellt, die nur die Elemente enthält, die ich möchte".

BEARBEITUNG: geändert "L = ..." zu "L [:] = ..." laut Alex Martellis Antwort auf this question.

+0

Wie gut skaliert das zu großen Listen? – jmucchiello

+1

Es stellt sich heraus, dass dies umso besser ist, je länger die Listen bekommen. Siehe diesen Testcode: http://pastebin.com/f5bf9e3e8. – PaulMcG

+0

Dies ist der Weg, dies zu tun; Beachten Sie, dass "I" eine Menge sein sollte, keine Liste. –

9
for i in I: 
    del L[i] 

wird nicht funktionieren, weil sie (je nach Bestellung) der Iterator ungültig machen kann - dies wird in der Regel als einige Elemente auftauchen, die Sie in der Liste verbleibenden löschen soll.

Es ist immer sicher, Elemente aus der Liste in der umgekehrten Reihenfolge ihrer Indizes zu löschen. Der einfachste Weg, dies zu tun ist mit sortierter():

for i in sorted(I, reverse=True): 
    del L[i] 
+0

Das ist eine großartige Idee. : D Ich bin mir nicht sicher, ob umgekehrt (Liste (I)) korrekt ist? Aber ich bekomme die Idee: Sortiere die Indizes in I in umgekehrter Reihenfolge und DANN lösche. – Ezequiel

+0

Sie brauchen die Liste(), da Sie nicht umgekehrt() direkt auf einem Satz aufrufen können. – dcrosta

+0

ack, das war dumm! ich meinte nicht umgekehrt (liste (...)), ich meinte sortiert (..., reverse = True) – dcrosta

1

Wenn Ihre ursprüngliche Listendaten sicher in einen Satz gedreht werden kann (dh alle eindeutigen Werte und muss nicht um die Ordnung aufrechtzuerhalten), können Sie auch Set-Operationen verwenden könnte: vielleicht auch tun

Lset = set(L) 
newset = Lset.difference(I) 

Sie könnten etwas mit einer Tasche/Multiset, obwohl es die Mühe wahrscheinlich nicht wert ist. Die zweite listcomp-Lösung von Paul McGuire ist für die meisten Fälle sicherlich die beste Lösung.

-1
L = [ item for item in L if L.index(item) not in I ] 
4

Sie können numpy.delete wie folgt verwenden:

import numpy as np 
a = ['a', 'l', 3.14, 42, 'u'] 
I = [1, 3, 4] 
np.delete(a, I).tolist() 
# Returns: ['a', '3.14'] 

Wenn Sie nicht mit einem numpy Array am Ende landen nichts ausmacht, können Sie die .tolist() auslassen. Sie sollten auch einige wesentliche Geschwindigkeitsverbesserungen sehen, was diese zu einer besser skalierbaren Lösung macht. Ich habe es nicht bewertet, aber numpy Operationen sind kompilierter Code in C oder Fortran geschrieben.

Verwandte Themen