¿Hay una manera simple de eliminar un elemento de lista por valor?

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

del a[b]
print(a)

Lo anterior muestra el siguiente error:

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

Entonces tengo que hacer esto:

a = [1, 2, 3, 4]

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

print(a)

¿Pero no hay una manera más simple de hacer esto?

zjm1126
fuente
14
Calcula el índice de 6 en su lista. Pero 6 no está en tu lista ... ¿qué se supone que sucederá? :)
Johannes Charra
55
esto no tiene nada que ver con eliminar un valor en una lista, ya que su código no alcanza la instrucción del. Tal vez deberías retitúlelo "cómo consigo el índice de un valor que no está en una lista Respuesta obvia -. No se puede.
David Kirby
57
@ Dave Bueno, en realidad no. Quiere eliminar un elemento de la lista, independientemente de si existe o no, para no obtener el índice de un elemento inexistente. La pregunta está bien hecha.
ibz
Además del punto, pero un desnudo exceptes una mala práctica . Usar except Exceptioncomo mínimo.
wjandrea

Respuestas:

1565

Para eliminar la primera aparición de un elemento en una lista, simplemente use list.remove:

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

Tenga en cuenta que no elimina todas las ocurrencias de su elemento. Use una lista de comprensión para eso.

>>> 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
fuente
144
Falla si el elemento no está en la lista. :)
ibz
21
La comprensión de la lista @ibz no falla incluso si el elemento no está en la lista, ¿verdad?
IsaacS
76
Para aclarar para cualquier persona que descreme, "falla" en el sentido de que genera una excepción ValueError.
Casey Falk
10
La comprensión de la lista cambia la referencia de la lista, por lo que si hay una copia de la referencia en alguna parte, la eliminación no seguirá.
Sebastien
¿Cuál es la complejidad de si removees O (n)?
Rasmi Ranjan Nayak
184

Por lo general, Python lanzará una excepción si le dice que haga algo que no puede, por lo que deberá hacer lo siguiente:

if c in a:
    a.remove(c)

o:

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

Una excepción no es necesariamente algo malo siempre y cuando sea una que esté esperando y maneje adecuadamente.

Dave Webb
fuente
99
Es mejor prevenir que curar. Si primero puede verificar condiciones excepcionales (ejemplo a), debería hacerlo.
Gusdor
82
Si bien esto es cierto en otros idiomas, en Python es "más fácil pedir perdón que permiso". docs.python.org/2/glossary.html#term-eafp
Dave Webb
66
@Gusdor: si la lista se comparte entre subprocesos, entonces a.remove(c)podría fallar a pesar de la if c in averificación ( apodría modificarse en otro subproceso después de la c in averificación pero antes de la a.remove(c)llamada). try/excepto se podrían usar cerraduras para evitar la condición de carrera.
jfs
77
@JFSebastian si una lista se comparte entre hilos y no está aplicando secciones críticas, entonces tiene problemas más grandes.
Gusdor
44
@Gusdor, el idioma de Pythonique es intentar sin verificar y detectar la excepción si ocurre. Es más eficiente (solo una búsqueda en lugar de dos), aunque un poco más feo
Jeet
80

Tu puedes hacer

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

pero arriba necesita buscar 6 en la lista 2 veces, así que intente, excepto sería más rápido

try:
    a.remove(6)
except:
    pass

fuente
55

Considerar:

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

Para eliminar todas las ocurrencias, puede usar la función de filtro en python. Por ejemplo, se vería así:

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

Por lo tanto, mantendría todos los elementos de a != 2.

Para sacar uno de los elementos, use

a.remove(2)
Mathwizurd
fuente
¿Por qué te envuelves filter()en otro list()? Según el manual, ya devuelve una lista.
Olaf Dietsche
8
@OlafDietsche En Python 3.x, devuelve un objeto de filtro (en 2.x, devuelve una lista), por lo que tengo que convertir "a" en una lista para que tenga alguna funcionalidad.
mathwizurd
17

Aquí se explica cómo hacerlo en el lugar (sin comprensión de la lista):

def remove_all(seq, value):
    pos = 0
    for item in seq:
        if item != value:
           seq[pos] = item
           pos += 1
    del seq[pos:]
jfs
fuente
Muy inteligente, realmente me gusta, desafortunadamente parece ser tan ineficiente como la respuesta más popular. La solución de Gil es en realidad mucho más rápida para listas gigantes con solo unas pocas ocurrencias del valor que desea eliminar.
Larold
1
@Larold La forma más rápida sería una pregunta separada. Mi dinero está en la lista de comprensión en el caso general. Esta solución debería funcionar realmente bien si el valor es frecuente en la lista de entrada y no se utiliza la comprensión de la lista. Pruebe Pypy, datos numpy en Cython. [La respuesta de @ Gill es O(n*n)innecesaria (compárese 1e6 y 1e12; no quiere arriesgarse a esto último). while 1: L.remove(value)y volver a ValueErrorfuncionar podría funcionar bien con unas pocas valuelistas pequeñas en CPython.
jfs
13

Si sabe qué valor eliminar, aquí hay una manera simple (tan simple como se me ocurre, de todos modos):

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

Usted obtendrá [0, 0, 2, 3, 4]

Gil
fuente
44
¿Por qué no usar while 1 in a:como estructura de bucle?
TerminalDilettante
12
Aquí es O(n^2)donde estaría una comprensión O(n).
Físico loco
1
Por supuesto, @MadPhysicist tiene razón, y la versión de TerminalDilettante es mucho más pitónica, incluso si no nos importa el rendimiento. En 2013 comencé a aprender Python y hoy en día me avergüenzo de lo que escribí en ese momento.
Gil
11

Otra posibilidad es usar un conjunto en lugar de una lista, si un conjunto es aplicable en su aplicación.

IE si sus datos no están ordenados y no tienen duplicados, entonces

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

Está libre de errores.

A menudo, una lista es solo un contenedor útil para artículos que en realidad no están ordenados. Hay preguntas sobre cómo eliminar todas las ocurrencias de un elemento de una lista. Si no quieres engañar en primer lugar, una vez más, un conjunto es útil.

my_set.add(3)

no cambia my_set desde arriba.

GreenAsJade
fuente
10

Como se indica en muchas otras respuestas, list.remove()funcionará, pero arroje un ValueErrorsi el elemento no estaba en la lista. Con Python 3.4+, hay un enfoque interesante para manejar esto, usando el Suppress contextmanager :

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

Encontrar un valor en una lista y luego eliminar ese índice (si existe) es más fácil usando el método remove de la lista:

>>> 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 hace esto a menudo, puede resumirlo en una función:

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

fuente
8

Este ejemplo es rápido y eliminará todas las instancias de un valor de la lista:

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
fuente
2
si haces esto, solo deberías seguir breakadelante except ValueError.
Anthon
8

En una linea:

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

a veces es útil.

Aún más fácil:

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

Si sus elementos son distintos, entonces bastará una simple diferencia de conjunto.

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
fuente
2
Si sus elementos son distintos y no le importa el orden .
Tom Zych
2

También podemos usar .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
fuente
2

Sobrescriba la lista indexando todo excepto los elementos que desea eliminar

>>> s = [5,4,3,2,1]
>>> s[0:2] + s[3:]
[5, 4, 2, 1]
kilojulios
fuente
2

Con un bucle for y una condición:

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

Y si desea eliminar algunos, pero no todos:

def cleaner(seq, value, occ):
    temp = []
    for number in seq:
        if number == value and occ:
            occ -= 1
            continue
        else:
            temp.append(number)
    return temp
usuario7970984
fuente
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
fuente
Es sin usar la función de filtro
Ravikiran D
1

Digamos, por ejemplo, que queremos eliminar todos los 1 de x. Así es como lo haría:

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

Ahora, este es un uso práctico de mi método:

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

Y este es mi método en una sola línea:

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

Ambos producen esto como una salida:

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

Espero que esto ayude. PD, tenga en cuenta que esto se escribió en la versión 3.6.2, por lo que es posible que deba ajustarlo para versiones anteriores.

Krohnus Melavea
fuente
1

Tal vez sus soluciones funcionen con ints, pero no me funcionan con dictionarys.

Por un lado, remove () no me ha funcionado. Pero tal vez funciona con tipos básicos. Supongo que el siguiente código también es la forma de eliminar elementos de la lista de objetos.

Por otro lado, 'del' tampoco ha funcionado correctamente. En mi caso, usando python 3.6: cuando trato de eliminar un elemento de una lista en un bucle 'for' con el comando 'del', python cambia el índice en el proceso y bucle se detiene prematuramente antes de tiempo. Solo funciona si elimina elemento por elemento en orden inverso . De esta manera, no cambia el índice de matriz de elementos pendientes cuando lo está revisando

Entonces, estoy acostumbrado:

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

donde 'lista' es como [{'clave1': valor1 '}, {' clave2 ': valor2}, {' clave3 ': valor3}, ...]

También puedes hacer más pitónico usando enumerate:

for i, element in enumerate(reversed(list)):
    if condition(element):
        del list[(i+1)*-1]
print(list)
David Martínez
fuente
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
fuente
0

Esto elimina todas las instancias de "-v"la matriz sys.argvy no se queja si no se encontraron instancias:

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

Puede ver el código en acción, en un archivo llamado 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
fuente
-1

esta es mi respuesta, solo use while y for

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
fuente