2009-09-20 21 views
12

Ho una lista L.Elimina molti elementi della lista (Python)

posso cancellare elemento i facendo:

del L[i] 

Ma cosa succede se ho una serie di indici non contigui da eliminare?

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

fare:

for i in I: 
    del L[i] 

non funzionerà.

Qualche idea?

+1

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

risposta

31

Eine Minuten bitte, Ich HAP eine kleine Problemo avec Diese Religione. - Eddie Izzard (facendo la sua impressione di Martin Lutero)

Cancellazione dal reverse-iterazione su un elenco di preservare l'iteratore è una soluzione comune a questo problema. Ma un'altra soluzione è quella di cambiare questo in un altro problema. Invece di eliminare elementi dall'elenco utilizzando alcuni criteri (nel tuo caso l'indice esiste in un elenco di indici da eliminare), crea un nuovo elenco che ometta gli elementi offensivi.

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

Del resto, da dove si arriva con gli indici in I, in primo luogo? È possibile combinare la logica di rimuovere gli indici e creare la nuova lista. Supponendo che questo è un elenco di oggetti e si desidera solo per mantenere quelli che passano una isValid prova:

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

Questo è molto più semplice rispetto:

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] 

Per la maggior parte, mi rivolgo qualche domanda su "come eliminare da un elenco gli elementi che non voglio" in "come creare un nuovo elenco contenente solo gli elementi che voglio".

MODIFICATO: modificato "L = ..." in "L [:] = ..." per risposta di Alex Martelli allo this question.

+0

Quanto bene scala le grandi liste? – jmucchiello

+1

Si scopre che questo fa meglio più a lungo si ottengono le liste. Vedi questo codice di prova: http://pastebin.com/f5bf9e3e8. – PaulMcG

+0

Questo è il modo per farlo; nota che "I" dovrebbe essere un set, non una lista. –

9
for i in I: 
    del L[i] 

non funziona, perché (a seconda dell'ordine) si può invalidare l'iteratore - questo solitamente si presenta come alcuni elementi che lo scopo di eliminare rimanente nella lista.

È sempre possibile eliminare elementi dall'elenco nell'ordine inverso dei loro indici. Il modo più semplice per farlo è con ordinato():

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

Questa è una grande idea. : D Non sono sicuro che l'inversione (lista (I)) sia corretta? Ma mi viene l'idea: ordina gli indici in I in ordine inverso e POI cancella. – Ezequiel

+0

è necessario l'elenco() poiché non è possibile chiamare il contrario() direttamente su un set. – dcrosta

+0

ack, quello era sciocco! non intendevo invertito (lista (...)), intendevo risolto (..., reverse = True) – dcrosta

1

Se i dati della lista originali possono tranquillamente essere trasformato in un set (vale a dire tutti i valori unici e non ha bisogno di mantenere l'ordine), è possibile utilizzare anche le operazioni di set:

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

Si potrebbe anche forse fare qualcosa con una borsa/multiset, anche se probabilmente non ne vale la pena. La seconda soluzione listcomp di Paul McGuire è sicuramente la soluzione migliore per la maggior parte dei casi.

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

È possibile utilizzare numpy.delete come segue:

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

Se non ti dispiace finire con un allineamento numpy alla fine, si può lasciare fuori il .tolist(). Dovreste vedere anche alcuni miglioramenti di velocità piuttosto importanti, rendendo questa soluzione più scalabile. Non l'ho confrontato, ma le operazioni numpy sono compilate in codice C o Fortran.

Problemi correlati