¿Cómo eliminar un elemento de una lista si existe?

Resuelto Zeynel asked hace 13 años • 8 respuestas

Obtengo new_tagde un campo de texto de formulario con self.response.get("new_tag")y selected_tagsde campos de casilla de verificación con

self.response.get_all("selected_tags")

Los combino así:

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

( f1.striplistes una función que elimina los espacios en blanco dentro de las cadenas de la lista).

Pero en el caso de que tag_listesté vacío (no se ingresan nuevas etiquetas) pero hay algunas selected_tags, new_tag_listcontiene una cadena vacía " ".

Por ejemplo, de logging.info:

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

¿Cómo me deshago de la cadena vacía?

Si hay una cadena vacía en la lista:

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

Pero si no hay una cadena vacía:

>>> 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"

Pero esto da:

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

¿Por qué sucede esto y cómo puedo solucionarlo?

Zeynel avatar Feb 07 '11 03:02 Zeynel
Aceptado

1) Estilo casi inglés:

Pruebe la presencia utilizando el inoperador y luego aplique el removemétodo.

if thing in some_list: some_list.remove(thing)

El removemétodo eliminará solo la primera aparición de thing, para eliminar todas las apariciones que pueda utilizar whileen lugar de if.

while thing in some_list: some_list.remove(thing)    
  • Bastante simple, probablemente mi elección. Para listas pequeñas (no puedo resistirme a las frases ingeniosas)

2) Tipo pato , estilo EAFP :

Esta actitud de disparar primero, hacer preguntas al final es común en Python. En lugar de probar de antemano si el objeto es adecuado, simplemente realice la operación y detecte las excepciones relevantes:

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

Por supuesto, la segunda cláusula excepto en el ejemplo anterior no sólo tiene un humor cuestionable sino que es totalmente innecesaria (el objetivo era ilustrar la escritura de pato para las personas que no están familiarizadas con el concepto).

Si espera que ocurran varias cosas:

while True:
    try:
        some_list.remove(thing)
    except ValueError:
        break
  • un poco detallado para este caso de uso específico, pero muy idiomático en Python.
  • esto funciona mejor que el n.° 1
  • PEP 463 propuso una sintaxis más corta para el uso simple try/except que sería útil aquí, pero no fue aprobada.

Sin embargo, con el administrador de contexto suprimir() de contextlib (introducido en Python 3.4), el código anterior se puede simplificar a esto:

with suppress(ValueError, AttributeError):
    some_list.remove(thing)

Nuevamente, si espera que algo ocurra varias veces:

with suppress(ValueError):
    while True:
        some_list.remove(thing)

3) Estilo funcional:

Alrededor de 1993, Python obtuvo lambda, y , cortesía de un hacker reduce()de Lisp que los extrañó y envió parches que funcionaban*. Puede utilizar para eliminar elementos de la lista:filter()map()filter

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

Hay un atajo que puede ser útil para su caso: si desea filtrar elementos vacíos (de hecho, elementos donde bool(item) == False, como None, cero, cadenas vacías u otras colecciones vacías), puede pasar Ninguno como primer argumento:

cleaned_list = filter(None, some_list)
  • [actualización] : en Python 2.x, filter(function, iterable)solía ser equivalente a [item for item in iterable if function(item)](o [item for item in iterable if item]si el primer argumento es None); en Python 3.x, ahora es equivalente a (item for item in iterable if function(item)). La sutil diferencia es que el filtro se utiliza para devolver una lista, ahora funciona como una expresión generadora; esto está bien si solo está iterando sobre la lista limpia y descartándola, pero si realmente necesita una lista, debe incluir la filter()llamada. con el list()constructor.
  • *Estas construcciones con sabor a Lispy se consideran un poco extrañas en Python. Alrededor de 2005, Guido incluso estaba hablando de eliminarlofilter , junto con sus compañeros mapy reduce(aún no se han ido, pero reducese trasladaron al módulo functools , que vale la pena echarle un vistazo si le gustan las funciones de alto nivel ).

4) Estilo matemático:

Las listas por comprensión se convirtieron en el estilo preferido para la manipulación de listas en Python desde que PEP 202 las introdujo en la versión 2.0 . La razón detrás de esto es que las listas por comprensión proporcionan una forma más concisa de crear listas en situaciones en las que actualmente se usarían bucles map()y filter()/o anidados.

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

Las expresiones generadoras fueron introducidas en la versión 2.4 por PEP 289 . Una expresión generadora es mejor para situaciones en las que realmente no necesita (o no desea) tener una lista completa creada en la memoria, como cuando solo desea iterar sobre los elementos uno a la vez. Si solo está iterando sobre la lista, puede pensar en una expresión generadora como una lista de comprensión evaluada de forma diferida :

for item in (x for x in some_list if x is not thing):
    do_your_thing_with(item)
  • Vea esta publicación de blog sobre la historia de Python de GvR .
  • Esta sintaxis está inspirada en la notación matemática del constructor de conjuntos .
  • Python 3 también ha establecido y dictado por comprensión .

Notas

  1. es posible que desee utilizar el operador de desigualdad !=en lugar de is not( la diferencia es importante )
  2. para los críticos de los métodos que implican una copia de la lista: contrariamente a la creencia popular, las expresiones generadoras no siempre son más eficientes que las listas por comprensión; perfile antes de quejarse
Paulo Scardine avatar Feb 06 '2011 20:02 Paulo Scardine

Como una sola línea:

>>> s = [u'', u'Hello', u'Cool', u'Glam']
>>> s.remove('') if '' in s else None # Does nothing if '' not in s
>>> s
['Hello', 'Cool', 'Glam']
>>> 
qwerty_url avatar Jun 22 '2021 04:06 qwerty_url