933 votes

Supprimer des éléments d'une liste lors de l'itération en Python

Je suis une itération sur une liste de tuples en Python, et je suis d'essayer de les enlever s'ils répondent à certains critères.

for tup in somelist:
    if determine(tup):
         code_to_remove_tup

Que dois-je utiliser à la place de code_to_remove_tup? Je ne peux pas comprendre comment faire pour supprimer l'élément dans ce mode.

1008voto

David Raznick Points 5074

Une compréhension de liste est le meilleur pour ce genre de boucle.

somelist = [x for x in somelist if determine(x)]

EDIT: Emplois " commentaire dit qu'il veut le 'déterminer' pour dire ce qui doit être supprimé. Ce serait alors juste.

somelist = [x for x in somelist if not determine(x)]

EDIT:

somelist[:] = [x for x in somelist if not determine(x)]

Brandon Corfman est correct, vous perdrez référence à la liste d'origine, sauf si vous faites de cette façon ( voir Alex Martelli la réponse pour plus de détails).

Aussi, j'ai aimé Cides " suggestion qui utilise itertools. Cependant il n'est pas non itérateur filterfalse, de sorte qu'il est.

from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))

655voto

Alex Martelli Points 330805

Les réponses suggérant interprétations de la liste sont PRESQUE correct, sauf qu'ils se construisent une complètement nouvelle liste, puis lui donner le même nom à l'ancienne liste, ils ne modifient PAS l'ancien liste à la place. C'est différent de ce que vous souhaitez faire par élimination sélective, comme dans @Lennart la suggestion de -- c'est plus rapide, mais si votre liste est accessible par de multiples références au fait que vous êtes juste de remettre en place l'une des références et de ne PAS modifier la liste de l'objet lui-même peut conduire à de subtils, désastreux bugs.

Heureusement, il est très facile à obtenir à la fois la vitesse de la liste des inclusions ET de la sémantique de la place de l'altération -- code:

somelist[:] = [tup for tup in somelist if determine(tup)]

Notez la subtile différence avec les autres réponses: ce n'est PAS de l'affectation à un barename - c'est de l'attribution d'une liste de tranche qui se passe juste pour l'ensemble de la liste, en remplacement de la liste de contenu au sein de la même liste Python objet, plutôt que de juste de remettre en place une référence (à partir de la liste précédente de l'objet à la nouvelle liste d'objet) comme les autres réponses.

366voto

Lennart Regebro Points 52510

Vous avez besoin d'une copie de la liste et itération sur le premier, ou l'itération échoue avec ce qui est peut-être à des résultats inattendus.

Par exemple (dépend du type de liste):

for tup in somelist[:]:
    etc....

Un exemple:

>>> list = range(10)
>>> for x in list:
...     list.remove(x)
>>> list
[1, 3, 5, 7, 9]

>>> list = range(10)
>>> for x in list[:]:
...     list.remove(x)
>>> list
[]

160voto

John Machin Points 39706
for i in xrange(len(somelist) - 1, -1, -1):
    if some_condition(somelist, i):
        del somelist[i]

Vous avez besoin de revenir en arrière sinon c'est un peu comme scier l'arbre de branche que vous êtes assis sur :-)

49voto

Eli Courtwright Points 53071

Votre meilleure approche pour un tel exemple serait une compréhension de liste

somelist = [tup for tup in somelist if determine(tup)]

Dans le cas où vous êtes en train de faire quelque chose de plus complexe que de faire appel à un determine de la fonction, je préfère la construction d'une nouvelle liste et simplement en ajoutant à cela que je vais. Par exemple

newlist = []
for tup in somelist:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)
somelist = newlist

La copie de la liste à l'aide de remove peut rendre votre code un peu plus propre, tel que décrit dans l'une des réponses ci-dessous. Vous devriez certainement pas le faire pour les très grandes listes, puisqu'il s'agit d'abord de la copie de l'ensemble de la liste, et aussi l'accomplissement de l' O(n) remove opération pour chaque élément est supprimé, ce qui en fait un O(n^2) de l'algorithme.

for tup in somelist[:]:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)

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