359 votes

Comment faire pour supprimer un élément dans une liste, si elle existe ? (Python)

Je reçois new_tag à partir d'un formulaire champ de texte avec

self.response.get("new_tag")

et

selected_tags

de case à cocher champs avec

self.response.get_all("selected_tags").

Je les combiner comme ceci:

tag_string = new_tag
new_tag_list = f1.striplist(tag_string.split(",") + selected_tags)

(f1.striplist est une fonction qui supprime les espaces blancs à l'intérieur des chaînes dans la liste.)

Mais dans le cas qui tag_list est vide (pas de nouvelles balises sont inscrits), mais il y a quelques selected_tags, new_tag_list contient une chaîne vide " ".

Par exemple, à partir d' logging.info:

***new_tag***
***selected_tags***[u'Hello', u'Cool', u'Glam']
***new_tag_list***[u'', u'Hello', u'Cool', u'Glam']

Comment puis-je me débarrasser de la chaîne vide?

Si il y a une chaîne vide dans la liste:

>>> s = [u'', u'Hello', u'Cool', u'Glam']
>>> i = s.index("")
>>> del s[i]
>>> s
[u'Hello', u'Cool', u'Glam']

Mais si il n'y a pas de chaîne vide:

>>> s = [u'Hello', u'Cool', u'Glam']
>>> if s.index(""):
        i = s.index("")
        del s[i]
    else:
        print "new_tag_list has no empty string"

Mais ce qui donne:

Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    if new_tag_list.index(""):
        ValueError: list.index(x): x not in list

Pourquoi est-ce? Et que proposez-vous comme solution? Merci!

935voto

Paulo Scardine Points 17518

1) la Quasi-style anglais:

Test de présence à l'aide de l' in l'opérateur, puis appliquer l' remove méthode.

if thing in some_list: some_list.remove(thing)

L' removeméthode consiste à retirer uniquement la première occurrence d' thing, afin de supprimer toutes les occurrences que vous pouvez utiliser while au lieu de if.

while thing in some_list: some_list.remove(thing)    
  • Assez Simple, probablement mon choix.pour les petites listes (ne peut pas résister one-liners)

2) le Canard tapé, l'aeap style:

Ce shoot-premier-poser des questions-dernière attitude est courante en Python. Au lieu de tester à l'avance si l'objet est adapté, à seulement procéder à l'opération et attraper les Exceptions pertinentes:

try:
    some_list.remove(thing)
except ValueError:
    pass # or scream: thing not in some_list!
except AttributeError:
    pass # call security, some_list not quacking like a list!

Si vous vous attendez à de multiples occurrences de la chose:

while True:
    try:
        some_list.remove(thing)
    except ValueError:
        break
  • un petit verbeux pour ce cas d'utilisation spécifiques, mais très idiomatiques en Python.
  • cela fonctionne mieux que le #1
  • PEP 463 proposé une syntaxe plus courte pour les try/except simple d'utilisation qui peut être utile ici, mais il n'a pas été approuvé.

3) style Fonctionnel:

Autour de 1993, Python got lambda, reduce(), filter() et map(), grâce à l'un de Lisp hacker qui l'ont manqué, et soumis de travail correctifs*. Vous pouvez utiliser filter pour supprimer des éléments de la liste:

is_not_thing = lambda x: x is not thing
cleaned_list = filter(is_not_thing, some_list)

Il y a un raccourci qui peut être utile pour votre cas: si vous souhaitez filtrer des éléments vides (en fait des objets où l' bool(item) == False, comme None, zéro, les cordes à vide ou d'autres collections vide), vous pouvez passer Aucun comme premier argument:

cleaned_list = filter(None, some_list)
  • [mise à jour]: en Python 2.x, filter(function, iterable) utilisé pour être équivalent à [item for item in iterable if function(item)] (ou [item for item in iterable if item] si le premier argument est - None); en Python 3.x, il est maintenant équivalent à (item for item in iterable if function(item)). La subtile différence est que le filtre utilisé pour renvoyer une liste, maintenant il fonctionne comme un générateur d'expression - c'est OK si vous avez seulement une itération sur la nettoyés liste et de s'en débarrasser, mais si vous avez vraiment besoin d'une liste, vous devez joindre l' filter() appel à l' list() constructeur.
  • *Ces Lispy aromatisé constructions sont considérées comme un petit alien en Python. Autour de 2005, Guido était parlons même tomber filter - le long de avec les compagnons map et reduce (ils ne sont pas encore parti, mais reduce a été déplacé dans le functools module, qui vaut le détour si vous aimez les hautes fonctions d'ordre).

4) Mathématiques style:

Interprétations de la liste est devenu le style préféré de la liste de manipulation en Python depuis introduite dans la version 2.0 par PEP 202. Le raisonnement derrière cela est que les interprétations de la Liste de fournir d'une manière plus concise pour créer des listes dans les situations où l' map() et filter() et/ou boucles imbriquées serait actuellement utilisé.

cleaned_list = [ x for x in some_list if x is not thing ]

Générateur d'expressions ont été introduites dans la version 2.4 par PEP 289. Un générateur d'expression est mieux pour les situations où vous n'avez pas vraiment besoin (ou envie) d'avoir une liste complète dans la mémoire - comme lorsque vous souhaitez effectuer une itération sur les éléments un à un. Si vous êtes seulement une itération sur la liste, vous pouvez penser à un générateur d'expression comme un paresseux évalué compréhension de liste:

for item in (x for x in some_list if x is not thing):
    do_your_thing_with(item)

Notes

  1. vous pouvez utiliser l'opérateur d'inégalité != au lieu de is not (la différence est importante)
  2. pour les critiques de méthodes impliquant une liste de copie: contrairement à la croyance populaire, générateur d'expressions ne sont pas toujours plus efficace que les interprétations de la liste - s'il vous plaît profil avant de vous plaindre

13voto

Tim Pietzcker Points 146308
<pre><code></code><p>Notez que cela va supprimer uniquement une seule instance d’une chaîne vide dans votre liste (comme votre code aurait, trop). Peut votre liste contient plus d’un ?</p></pre>

9voto

phihag Points 89765

Si ne trouve pas la chaîne recherchée, il lève le que vous voyez. Soit prendre la ValueError :

utilisation ou`` , qui renvoie -1 dans cette affaire.

5voto

dfichter Points 845

EEK, ne faites rien qui complique :))

Juste vos balises.renvoie `` pour des chaînes vides, alors au lieu de

vous devez écrire

ou mieux encore, mettez cette logique à l’intérieur `` afin qu’il ne retourne pas en premier lieu les chaînes vides.

5voto

Dane White Points 734

Voici un autre one-liner approche à jeter là-bas:

next((some_list.pop(i) for i, l in enumerate(some_list) if l == thing), None)

Il n'est pas de créer une liste de copie, ne pas faire en plusieurs passages par le biais de la liste, n'a pas besoin d'autres la gestion des exceptions, et renvoie à la correspondance de l'objet ou Aucune si il n'y a pas un match. Seul problème est qu'il en fait une longue déclaration.

En général, lorsque vous cherchez un one-liner solution qui n'est pas de lancer des exceptions, next() est le chemin à parcourir, car c'est l'une des rares fonctions Python qui prend en charge un argument par défaut.

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