79 votes

Python : Suppression d'un élément de liste lors de l'itération sur une liste

Je suis en train d'itérer sur une liste d'éléments en Python, d'effectuer une action sur celle-ci, puis de les supprimer s'ils répondent à certains critères.

for element in somelist:
    do_action(element)
    if check(element):
        remove_element_from_list

Que dois-je utiliser à la place de remove_element ? J'ai vu des questions similaires posées, mais je remarque la présence de la partie do_action qui doit être exécutée pour tous les éléments et qui élimine donc la solution d'utiliser des filtres.

141voto

bluepnume Points 3587

Vous pouvez toujours itérer sur une copie de la liste, ce qui vous laisse libre de modifier l'original :

for item in list(somelist):
  ...
  somelist.remove(item)

122voto

John Machin Points 39706

Pour répondre à ces critères : modifier la liste originale in situ, pas de copie de la liste, un seul passage, travaux une solution traditionnelle est d'itérer à l'envers :

for i in xrange(len(somelist) - 1, -1, -1):
    element = somelist[i]
    do_action(element)
    if check(element):
        del somelist[i]

Bonus : ne fait pas len(somelist) à chaque itération. Fonctionne sur toutes les versions de Python (au moins jusqu'à la 1.5.2) ... s/xrange/range/ pour 3.X.

Mise à jour : Si vous voulez itérer vers l'avant C'est possible, mais plus délicat et plus laid :

i = 0
n = len(somelist)
while i < n:
    element = somelist[i]
    do_action(element)
    if check(element):
        del somelist[i]
        n = n - 1
    else:
        i = i + 1

10voto

zeekay Points 22640

Liste comp :

results = [x for x in (do_action(element) for element in somelist) if check(element)]

8voto

gnibbler Points 103484
for element in somelist:
    do_action(element)
somelist[:] = (x for x in somelist if not check(x))

Si vous avez vraiment besoin de le faire en une seule passe sans copier la liste

i=0
while i < len(somelist):
    element = somelist[i] 
    do_action(element)
    if check(element):
        del somelist[i]
    else:
        i+=1

7voto

Riccardo Galli Points 2653

Vous pouvez toujours utiliser le filtre, en déplaçant vers une fonction extérieure la modification de l'élément (en itérant une seule fois).

def do_the_magic(x):
    do_action(x)
    return check(x)

# you can get a different filtered list
filter(do_the_magic,yourList)

# or have it modified in place (as suggested by Steven Rumbalski, see comment)
yourList[:] = itertools.ifilter(do_the_magic, yourList)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X