2009-08-30 5 views
10

En Java je peux le faire en utilisant un Iterator puis en utilisant la méthode .remove() du iterator pour enlever le dernier élément retourné par l'itérateur, comme ceci:Retirer les éléments que vous traversez une liste 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] 
*/ 

Comment ferais-je cela en Python? Je ne peux pas modifier la liste pendant que je l'itère dans une boucle for car cela provoque l'omission de la tâche (voir here). Et il ne semble pas y avoir un équivalent de l'interface Iterator de Java.

+0

I Je me demande si l'utilisation d'un itérateur inversé pourrait être une solution. Des pensées à ce sujet? Ce serait mieux que de faire une copie d'une liste. –

+0

http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python Il est demandé beaucoup ... –

Répondre

18

itérer sur une copie de la liste:

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

Pourquoi les couleurs [:] au lieu des couleurs? – hughdbrown

+4

'colors [:]' est une copie (un étrange, mais, soupir, façon idiomatique pour épeler 'list (colors)') afin qu'il ne soit pas affecté par les appels '.remove'. –

+1

La seule raison de l'appeler plus idiomatique est que la documentation du module de copie stdlib le fait référence. Malgré cela, j'utiliserais toujours list (otherlist) pour les copies (ou éventuellement copy.copy (autre chose)) –

26

meilleure approche en Python est de faire une nouvelle liste, idéalement dans un listcomp, le définir comme le [:] de l'ancien, par exemple:

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

PAS colors = que certaines réponses peuvent suggérer - que seul rebondit le nom et laissera finalement quelques références à l'ancien "corps" balançant; colors[:] = est BEAUCOUP mieux sur tous les points ;-).

+1

La compréhension de liste est le meilleur choix. – hughdbrown

+0

ou colors = liste (c pour c en couleurs si c! = 'Vert') – dugres

+0

@dugres: pas tout à fait: colors = list (...) ne rebondit pas. Alex a insisté sur l'idée qu'il vaut mieux ne pas laisser des listes inutiles dans la mémoire. – EOL

4

Vous pouvez utiliser la fonction de filtre:

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

ou vous pouvez aussi faire comme ce

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

Il n'y a aucun avantage à utiliser '.__ contains __()' sur ''green' dans les couleurs' –

+1

Plus, colors.remove() a seulement enlevé la * première * occurrence au lieu de toutes les occurrences. – EOL

+2

La solution pourrait être faite pour travailler, via: tandis que «vert» dans les couleurs: colors.remove («vert»). Bien sûr, c'est O (n ** 2), alors que les meilleures solutions sont O (n). –

Questions connexes