2012-10-01 19 views
10

Come si rimuove un elemento da un elenco se corrisponde a una sottostringa?Rimozione di un elemento dall'elenco corrispondente a una sottostringa - Python

Ho provato a rimuovere un elemento da un elenco utilizzando il metodo pop() e enumerate ma sembra che io mi manca alcuni elementi contigui che deve essere rimosso:

sents = ['@$\tthis sentences needs to be removed', 'this doesnt', 
    '@$\tthis sentences also needs to be removed', 
    '@$\tthis sentences must be removed', 'this shouldnt', 
    '# this needs to be removed', 'this isnt', 
    '# this must', 'this musnt'] 

for i, j in enumerate(sents): 
    if j[0:3] == "@$\t": 
    sents.pop(i) 
    continue 
    if j[0] == "#": 
    sents.pop(i) 

for i in sents: 
    print i 

uscita:

this doesnt 
@$ this sentences must be removed 
this shouldnt 
this isnt 
#this should 
this musnt 

output desiderato:

this doesnt 
this shouldnt 
this isnt 
this musnt 
+3

Caso classico di rimozione di elementi da un elenco mentre si sta iterando su tale elenco. Leggi le dozzine di altre domande relative allo Stack Overflow correlate a questo. Inoltre, consultare la [nota nei documenti] (http://docs.python.org/reference/compound_stmts.html#for). –

+1

si dovrebbe sempre evitare di cambiare la lunghezza di un contenitore mentre si scorre attraverso di esso, questa è una ricetta per il disastro – wim

+0

In generale, di solito è meglio creare un nuovo elenco filtrato piuttosto che provare a modificare un elenco sul posto. Gli algoritmi immutabili sono sempre più facili da ragionare (anche se non sempre è più facile capire come scrivere). Quando stai solo sostituendo i valori, a volte il guadagno in termini di efficienza del lavoro sul posto lo supera, ma quando stai eliminando o inserendo nel mezzo di un elenco, ottieni solitamente efficienza _worse_ insieme alla tua logica meno solida. – abarnert

risposta

20

Come abo ut qualcosa di semplice come:

>>> [x for x in sents if not x.startswith('@$\t') and not x.startswith('#')] 
['this doesnt', 'this shouldnt', 'this isnt', 'this musnt'] 
+0

ah una comprensione di lista, elegante! fammi provare. – alvas

+0

+1 per la risposta più pulita. – abarnert

8

Questo dovrebbe funzionare:

[i for i in sents if not ('@$\t' in i or '#' in i)] 

Se si desidera che solo le cose che iniziano con quelle specificate sentential utilizzare il metodo str.startswith(stringOfInterest)

+2

Direi che questo è migliore degli altri due per non presumere che le sottostringhe siano all'inizio – Frikster

9

Un'altra tecnica che utilizza filter

filter(lambda s: not (s[0:3]=="@$\t" or s[0]=="#"), sents) 

Il problema con il tuo approac originale h è quando sei nella voce di elenco i e determina che dovrebbe essere cancellato, lo rimuovi dall'elenco, che fa scorrere l'elemento i+1 nella posizione i. La prossima iterazione del ciclo sei all'indice i+1 ma l'articolo è in realtà i+2.

Ha senso?

+0

grazie per la spiegazione! schioccare una lista mentre enumerare è davvero sciocco. hahaha .. – alvas

+0

+1 per spiegare il problema. – abarnert

Problemi correlati