2011-12-17 33 views
8

lo que básicamente necesito es verificar cada elemento de una lista y si algunos criterios coinciden, quiero eliminarlo de la lista.cómo modificar correctamente el iterador de un bucle en python desde el bucle

Así, por ejemplo, digamos que

lista = [ 'a', 'b', 'c', 'd', 'e']

Básicamente quiero escribir (en principio y no es el código real que trato de implementar)

Si un elemento de la lista es 'b' o 'c' elimínelo de la lista y tome el siguiente.

Pero

for s in list: 
    if s=='b' or s=='c': 
     list.remove(s) 

falla porque cuando 'B' se elimina el bucle de toma 'd' y no 'c' como el siguiente elemento. Entonces, ¿hay alguna forma de hacerlo más rápido que almacenar los elementos en una lista separada y eliminarlos luego?

Gracias.

Respuesta

9

La manera más fácil es utilizar una copia de la lista - se puede hacer con una rebanada que se extiende "desde el principio" a la "final" de la lista, como esto:

for s in list[:]: 
    if s=='b' or s=='c': 
     list.remove(s) 

Usted han considerado esto, y esto es lo suficientemente simple para estar en su código, a menos que esta lista sea realmente grande, y en una parte crítica del código (como, en el ciclo principal de un juego de acción). En ese caso, a veces utilizar el siguiente idioma:

to_remove = [] 
for index, s in enumerate(list): 
    if s == "b" or s == "c": 
     to_remove.append(index) 

for index in reversed(to_remove): 
    del list[index] 

Por supuesto se puede recurrir a un bucle while en su lugar:

index = 0 
while index < len(list): 
    if s == "b" or s == "c": 
     del list[index] 
     continue 
    index += 1 
+0

jsbueno muchas gracias. Me siento un poco avergonzado por no pensar eso. ¡Gracias de nuevo! – tst

+0

Realmente quería un bucle dentro de un bucle y su último ejemplo fue perfecto. gracias de nuevo. – tst

1

Si estás bien con la creación de una copia de la lista que puede hacer como este (list comprehension):

[s for s in list if s != 'b' and s != 'c'] 
8

Su mejor no volver a inventar cosas que ya están disponibles. Use las funciones filter y lambda en estos casos. Es más pitónico y se ve más limpio.

filter(lambda x:x not in ['b','c'],['a','b','c','d','e']) 

Alternativamente, puede utilizar la lista de comprensión

[x for x in ['a','b','c','d','e'] if x not in ['b','c']] 
+0

En realidad, la comprensión de la lista en su segundo ejemplo es "más Pythonic" que la combinación de filtro y lambda. – jsbueno

+0

gracias pero necesitaba poner uno de esos bucles en otro y de esta manera las cosas pueden volverse realmente complicadas. – tst

3

Esto es exactamente lo que está diseñado para itertools.ifilter.

from itertools import ifilter 

ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e']) 

le devolverá un generador para su lista. Si realmente necesita una lista, puede crear utilizando una de las técnicas estándar para la conversión de un generador a una lista:

list(ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e'])) 

o

[x for x in ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e'])] 
Cuestiones relacionadas