2009-08-30 21 views
10

En Java que pueda hacer mediante el uso de un Iterator y luego utilizando el método del iterador .remove() para eliminar el último elemento devuelto por el iterador, así:Eliminar elementos a medida que atraviesan una lista en Python

import java.util.*; 

public class ConcurrentMod { 
    public static void main(String[] args) { 
     List<String> colors = new ArrayList<String>(Arrays.asList("red", "green", "blue", "purple")); 
     for (Iterator<String> it = colors.iterator(); it.hasNext();) { 
      String color = it.next(); 
      System.out.println(color); 
      if (color.equals("green")) 
       it.remove(); 
     } 
     System.out.println("At the end, colors = " + colors); 
    } 
} 

/* Outputs: 
red 
green 
blue 
purple 
At the end, colors = [red, blue, purple] 
*/ 

¿Cómo haría esto en Python? No puedo modificar la lista mientras la repito en un ciclo for porque hace que se omitan cosas (consulte here). Y no parece haber un equivalente de la interfaz Iterator de Java.

+0

I pregunto si usar un iterador reverso podría ser una solución. Tiene alguna idea sobre esto? Sería mejor que hacer una copia de una lista. –

+0

http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python Se pregunta mucho ... –

Respuesta

18

repetir un copia de la lista:

for c in colors[:]: 
    if c == 'green': 
     colors.remove(c) 
+0

¿Por qué colores [:] en lugar de colores? – hughdbrown

+4

'colours [:]' es una copia (una forma extraña pero idiomática de deletrear 'list (colors)') para que no se vea afectada por las llamadas '.remove'. –

+1

La única razón para llamarlo más idiomático es porque la documentación del módulo de copia stdlib lo hace referencia. A pesar de eso, todavía utilizaría list (otherlist) para copias (o posiblemente copy.copy (otherthing)) –

26

mejor enfoque en Python es hacer una nueva lista, idealmente en una listcomp, configurándolo como el [:] de la antigua, por ejemplo:

colors[:] = [c for c in colors if c != 'green'] 
NO

colors = como algunas respuestas pueden sugerir - que sólo vuelve a unir el nombre y eventualmente dejará algunas referencias al antiguo "cuerpo" colgando; colors[:] = es MUCHO mejor en todos los aspectos ;-).

+1

La comprensión de la lista es la mejor opción. – hughdbrown

+0

o colores = lista (c para c en colores si c! = 'Verde') – dugres

+0

@dugres: no exactamente: colors = list (...) no vuelve a enlazar. Alex insistió en la idea de que es mejor no dejar listas inútiles colgando en la memoria. – EOL

4

Se puede utilizar la función de filtro:

>>> colors=['red', 'green', 'blue', 'purple'] 
>>> filter(lambda color: color != 'green', colors) 
['red', 'blue', 'purple'] 
>>> 
0

o también se puede hacer como esto

>>> colors = ['red', 'green', 'blue', 'purple'] 
>>> if colors.__contains__('green'): 
...  colors.remove('green') 
+3

No hay ventaja en el uso de '.__ contains __()' over ''green' en colores' –

+1

Plus, colors.remove() solo eliminó la * primera * ocurrencia en lugar de todas las ocurrencias. – EOL

+2

La solución se puede hacer funcionar, a través de: mientras que 'verde' en colores: colores.remove ('verde'). Por supuesto, esto es O (n ** 2), mientras que las mejores soluciones son O (n). –

Cuestiones relacionadas