Existe-t-il un moyen simple de supprimer un élément de liste par valeur?

943
a = [1, 2, 3, 4]
b = a.index(6)

del a[b]
print(a)

Ce qui précède montre l'erreur suivante:

Traceback (most recent call last):
  File "D:\zjm_code\a.py", line 6, in <module>
    b = a.index(6)
ValueError: list.index(x): x not in list

Je dois donc faire ceci:

a = [1, 2, 3, 4]

try:
    b = a.index(6)
    del a[b]
except:
    pass

print(a)

Mais n'y a-t-il pas un moyen plus simple de le faire?

zjm1126
la source
14
Vous calculez l'indice de 6 dans votre liste. Mais 6 n'est pas dans votre liste ... alors qu'est-ce qui est censé se passer? :)
Johannes Charra
5
cela n'a rien à voir avec la suppression d'une valeur dans une liste, car votre code n'atteint pas l'instruction del. Vous devriez peut-être le renommer "comment puis-je obtenir l'index d'une valeur qui ne figure pas dans une liste. Réponse évidente - vous ne pouvez pas.
Dave Kirby
57
@ Dave Eh bien, pas vraiment. Il souhaite supprimer un élément de la liste, qu'il existe ou non, pour ne pas obtenir l'index d'un élément inexistant. La question est bien posée.
ibz
A côté du point, mais une mise à nu exceptest une mauvaise pratique . Utilisez except Exceptionau minimum.
wjandrea

Réponses:

1566

Pour supprimer la première occurrence d'un élément dans une liste, utilisez simplement list.remove:

>>> a = ['a', 'b', 'c', 'd']
>>> a.remove('b')
>>> print(a)
['a', 'c', 'd']

Gardez à l'esprit qu'il ne supprime pas toutes les occurrences de votre élément. Utilisez une liste de compréhension pour cela.

>>> a = [10, 20, 30, 40, 20, 30, 40, 20, 70, 20]
>>> a = [x for x in a if x != 20]
>>> print(a)
[10, 30, 40, 30, 40, 70]
Johannes Charra
la source
144
Échoue si l'élément n'est pas dans la liste. :)
ibz
21
La compréhension de la liste @ibz n'échoue pas même si l'élément n'est pas dans la liste, n'est-ce pas?
IsaacS
76
Pour clarifier pour quiconque écrémant, il "échoue" dans le sens où il déclenche une exception ValueError.
Casey Falk
10
La compréhension de la liste change la référence de la liste, donc s'il y a une copie de la référence quelque part, la suppression ne suivra pas.
Sebastien
Quelle est la complexité de removeest-ce O (n)?
Rasmi Ranjan Nayak
184

Habituellement, Python lèvera une exception si vous lui dites de faire quelque chose qu'il ne peut pas, vous devrez donc faire soit:

if c in a:
    a.remove(c)

ou:

try:
    a.remove(c)
except ValueError:
    pass

Une exception n'est pas nécessairement une mauvaise chose tant qu'elle est attendue et gérée correctement.

Dave Webb
la source
9
Mieux vaut prévenir que guérir. Si vous pouvez d'abord vérifier les conditions exceptionnelles (exemple a), vous devriez.
Gusdor
82
Bien que cela soit vrai dans d'autres langues, en Python, il est "plus facile de demander pardon que permission". docs.python.org/2/glossary.html#term-eafp
Dave Webb
6
@Gusdor: si la liste est partagée entre les threads, elle a.remove(c)peut quand même échouer malgré la if c in avérification ( apourrait être modifiée dans un autre thread après la c in avérification mais avant l' a.remove(c)appel). try/exceptou des serrures pourraient être utilisées pour éviter les conditions de course.
jfs
7
@JFSebastian si une liste est partagée entre les threads et que vous n'appliquez pas de sections critiques, vous avez de plus gros problèmes.
Gusdor
4
@Gusdor, l'idiome Pythonique est d'essayer sans vérifier et d'attraper l'exception si elle se produit. Il est plus efficace (une seule recherche au lieu de deux), quoique un peu plus laid
Jeet
80

Tu peux faire

a=[1,2,3,4]
if 6 in a:
    a.remove(6)

mais ci-dessus, il faut rechercher 6 dans la liste 2 fois, alors essayez sauf, ce serait plus rapide

try:
    a.remove(6)
except:
    pass
VOUS
la source
55

Considérer:

a = [1,2,2,3,4,5]

Pour supprimer toutes les occurrences, vous pouvez utiliser la fonction de filtrage en python. Par exemple, cela ressemblerait à:

a = list(filter(lambda x: x!= 2, a))

Ainsi, il conserverait tous les éléments de a != 2.

Pour retirer simplement l'un des objets, utilisez

a.remove(2)
mathwizurd
la source
Pourquoi en enveloppez-vous filter()un autre list()? Selon le manuel, il renvoie déjà une liste.
Olaf Dietsche du
8
@OlafDietsche En Python 3.x, il retourne un objet filtre (en 2.x, il retourne une liste), donc je dois lancer "a" dans une liste pour qu'il ait une fonctionnalité.
mathwizurd
17

Voici comment le faire sur place (sans compréhension de la liste):

def remove_all(seq, value):
    pos = 0
    for item in seq:
        if item != value:
           seq[pos] = item
           pos += 1
    del seq[pos:]
jfs
la source
Très intelligent - j'aime vraiment ça - malheureusement, il semble être aussi inefficace que la réponse la plus populaire. La solution de gil est en fait beaucoup plus rapide pour les listes géantes avec seulement quelques occurrences de la valeur que vous souhaitez supprimer.
Larold
1
@Larold Le moyen le plus rapide serait une question distincte. Mon argent est sur la liste de compréhension dans le cas général. Cette solution devrait très bien fonctionner si la valeur est fréquente dans la liste d'entrée et que la compréhension de la liste n'est pas utilisée. Essayez Pypy, numpy data en Cython. [@ La réponse de Gill est O(n*n)inutilement (comparez 1e6 et 1e12 - vous ne voulez pas risquer ce dernier). while 1: L.remove(value)et le retour ValueErrorpourrait bien fonctionner avec quelques values ou petites listes dans CPython.
jfs
13

Si vous savez quelle valeur supprimer, voici un moyen simple (aussi simple que je puisse penser, de toute façon):

a = [0, 1, 1, 0, 1, 2, 1, 3, 1, 4]
while a.count(1) > 0:
    a.remove(1)

Tu auras [0, 0, 2, 3, 4]

gil
la source
4
Pourquoi ne pas l'utiliser while 1 in a:comme structure de boucle?
TerminalDilettante
12
C'est O(n^2)là que serait une compréhension O(n).
Mad Physicist
1
Bien sûr, @MadPhysicist a raison, et la version de TerminalDilettante est beaucoup plus pythonique, même si nous ne nous soucions pas des performances. 2013 était juste que je commençais à apprendre le Python et de nos jours j'ai assez souvent honte de ce que j'ai écrit à l'époque.
gil
11

Une autre possibilité consiste à utiliser un ensemble au lieu d'une liste, si un ensemble est applicable dans votre application.

IE si vos données ne sont pas commandées et ne contiennent pas de doublons, alors

my_set=set([3,4,2])
my_set.discard(1)

est sans erreur.

Souvent, une liste n'est qu'un conteneur pratique pour les articles qui ne sont en fait pas classés. Il y a des questions qui demandent comment supprimer toutes les occurrences d'un élément d'une liste. Si vous ne voulez pas de dupes en premier lieu, une fois de plus, un ensemble est pratique.

my_set.add(3)

ne change pas mon_ensemble d'en haut.

GreenAsJade
la source
10

Comme indiqué par de nombreuses autres réponses, list.remove()fonctionnera, mais lancez un ValueErrorsi l'élément n'était pas dans la liste. Avec python 3.4+, il existe une approche intéressante pour gérer cela, en utilisant le gestionnaire de contexte de suppression :

from contextlib import suppress
with suppress(ValueError):
    a.remove('b')
Felk
la source
8

Il est plus facile de trouver une valeur dans une liste, puis de supprimer cet index (s'il existe) en utilisant simplement la méthode de suppression de la liste:

>>> a = [1, 2, 3, 4]
>>> try:
...   a.remove(6)
... except ValueError:
...   pass
... 
>>> print a
[1, 2, 3, 4]
>>> try:
...   a.remove(3)
... except ValueError:
...   pass
... 
>>> print a
[1, 2, 4]

Si vous le faites souvent, vous pouvez le récapituler dans une fonction:

def remove_if_exists(L, value):
  try:
    L.remove(value)
  except ValueError:
    pass

la source
8

Cet exemple est rapide et supprimera toutes les instances d'une valeur de la liste:

a = [1,2,3,1,2,3,4]
while True:
    try:
        a.remove(3)
    except:
        break
print a
>>> [1, 2, 1, 2, 4]
Chase Adams
la source
2
si vous faites cela, vous ne devriez vraiment que breakle faire except ValueError.
Anthon
8

En une seule ligne:

a.remove('b') if 'b' in a else None

parfois c'est utile.

Encore plus simple:

if 'b' in a: a.remove('b')
Andrey Suglobov
la source
7

Si vos éléments sont distincts, une simple différence d'ensemble fera l'affaire.

c = [1,2,3,4,'x',8,6,7,'x',9,'x']
z = list(set(c) - set(['x']))
print z
[1, 2, 3, 4, 6, 7, 8, 9]
Pagol
la source
2
Si vos éléments sont distincts et que vous ne vous souciez pas de la commande .
Tom Zych
2

Nous pouvons également utiliser .pop:

>>> lst = [23,34,54,45]
>>> remove_element = 23
>>> if remove_element in lst:
...     lst.pop(lst.index(remove_element))
... 
23
>>> lst
[34, 54, 45]
>>> 
SuperNova
la source
2

Écraser la liste en indexant tout sauf les éléments que vous souhaitez supprimer

>>> s = [5,4,3,2,1]
>>> s[0:2] + s[3:]
[5, 4, 2, 1]
kilojoules
la source
2

Avec une boucle for et une condition:

def cleaner(seq, value):    
    temp = []                      
    for number in seq:
        if number != value:
            temp.append(number)
    return temp

Et si vous souhaitez supprimer certains, mais pas tous:

def cleaner(seq, value, occ):
    temp = []
    for number in seq:
        if number == value and occ:
            occ -= 1
            continue
        else:
            temp.append(number)
    return temp
user7970984
la source
1
 list1=[1,2,3,3,4,5,6,1,3,4,5]
 n=int(input('enter  number'))
 while n in list1:
    list1.remove(n)
 print(list1)
Ravikiran D
la source
C'est sans utiliser la fonction de filtre
Ravikiran D
1

Disons par exemple que nous voulons supprimer tous les 1 de x. Voici comment je procéderais:

x = [1, 2, 3, 1, 2, 3]

Maintenant, ceci est une utilisation pratique de ma méthode:

def Function(List, Unwanted):
    [List.remove(Unwanted) for Item in range(List.count(Unwanted))]
    return List
x = Function(x, 1)
print(x)

Et voici ma méthode en une seule ligne:

[x.remove(1) for Item in range(x.count(1))]
print(x)

Les deux produisent ceci en sortie:

[2, 3, 2, 3, 2, 3]

J'espère que cela t'aides. PS, veuillez noter que cela a été écrit dans la version 3.6.2, vous devrez donc peut-être l'ajuster pour les anciennes versions.

Krohnus Melavea
la source
1

Peut-être que vos solutions fonctionnent avec des ints, mais cela ne fonctionne pas pour moi avec des dictionnaires.

D'une part, remove () n'a pas fonctionné pour moi. Mais peut-être que cela fonctionne avec les types de base. Je suppose que le code ci-dessous est également le moyen de supprimer des éléments de la liste d'objets.

En revanche, «del» n'a pas fonctionné correctement non plus. Dans mon cas, en utilisant python 3.6: lorsque j'essaie de supprimer un élément d'une liste dans une commande 'for' bucle avec 'del', python modifie l'index dans le processus et bucle s'arrête prématurément avant l'heure. Cela ne fonctionne que si vous supprimez élément par élément dans l' ordre inverse . De cette façon, vous ne modifiez pas l'index du tableau des éléments en attente lorsque vous le parcourez

Ensuite, je l'ai utilisé:

c = len(list)-1
for element in (reversed(list)):
    if condition(element):
        del list[c]
    c -= 1
print(list)

où 'list' est comme [{'key1': value1 '}, {' key2 ': value2}, {' key3 ': value3}, ...]

Vous pouvez également faire plus de pythonic en utilisant énumérer:

for i, element in enumerate(reversed(list)):
    if condition(element):
        del list[(i+1)*-1]
print(list)
David Martínez
la source
0
arr = [1, 1, 3, 4, 5, 2, 4, 3]

# to remove first occurence of that element, suppose 3 in this example
arr.remove(3)

# to remove all occurences of that element, again suppose 3
# use something called list comprehension
new_arr = [element for element in arr if element!=3]

# if you want to delete a position use "pop" function, suppose 
# position 4 
# the pop function also returns a value
removed_element = arr.pop(4)

# u can also use "del" to delete a position
del arr[4]
Brijesh Kushwaha
la source
0

Cela supprime toutes les instances de "-v"du tableau sys.argvet ne se plaint pas si aucune instance n'a été trouvée:

while "-v" in sys.argv:
    sys.argv.remove('-v')

Vous pouvez voir le code en action, dans un fichier appelé speechToText.py:

$ python speechToText.py -v
['speechToText.py']

$ python speechToText.py -x
['speechToText.py', '-x']

$ python speechToText.py -v -v
['speechToText.py']

$ python speechToText.py -v -v -x
['speechToText.py', '-x']
Mike Slinn
la source
-1

c'est ma réponse, utilisez simplement pendant et pour

def remove_all(data, value):
    i = j = 0
    while j < len(data):
        if data[j] == value:
            j += 1
            continue
        data[i] = data[j]
        i += 1
        j += 1
    for x in range(j - i):
        data.pop()
guoxy2016
la source