Tengo una lista de cadenas. Tengo una función que da una cadena devuelve 0 o 1. ¿Cómo puedo eliminar todas las cadenas en la lista para la cual la función devuelve 0?¿cuál es una manera rápida de eliminar todos los elementos de una lista que no cumple con una restricción?
Respuesta
[x for x in lst if fn(x) != 0]
Esta es una lista de "comprensión", uno de los mejores piezas de azúcar sintáctica que a menudo lleva a líneas de código en otros idiomas y declaraciones de variables adicionales de Python, etc.
Ver: http://docs.python.org/tutorial/datastructures.html#list-comprehensions
edit: vea la parte inferior para obtener la mejor respuesta.
Si necesita mutar una lista existente, por ejemplo porque tiene otra referencia en otro lugar, necesitará realmente remove
los valores de la lista.
No estoy al tanto de cualquier función en Python, pero algo como esto iba a funcionar (código no probado):
def cull_list(lst, pred):
"""Removes all values from ``lst`` which for which ``pred(v)`` is false."""
def remove_all(v):
"""Remove all instances of ``v`` from ``lst``"""
try:
while True:
lst.remove(v)
except ValueError:
pass
values = set(lst)
for v in values:
if not pred(v):
remove_all(v)
Una alternativa probablemente más eficientes que pueden parecer un poco demasiado como código C para el gusto de algunas personas:
def efficient_cull_list(lst, pred):
end = len(lst)
i = 0
while i < end:
if not pred(lst[i]):
del lst[i]
end -= 1
else:
i += 1
edición ...: Aaron como señaló en los comentarios, esto se puede hacer mucho más limpiamente con algo como
def reversed_cull_list(lst, pred):
for i in range(len(lst) - 1, -1, -1):
if not pred(lst[i]):
del lst[i]
... editar
El truco con estas rutinas es que el uso de una función como enumerate
, según lo sugerido por otro (s) respuesta (s), no se tendrá en cuenta el hecho de que los elementos de la lista ha sido eliminada. La única forma (que yo sepa) de hacer eso es simplemente rastrear el índice manualmente en lugar de permitir que python haga la iteración. Hay muchas posibilidades de encontrar un compromiso velocidad de allí, por lo que puede llegar a ser mejor sólo para hacer algo como
lst[:] = (v for v in lst if pred(v))
realidad, ahora que lo pienso, esto es, con mucho, la forma más sensata de hacer un 'en -place 'filter en una lista. Los valores del generador se repiten antes de llenar los elementos de lst
, por lo que no hay problemas de conflicto de índice. Si quieres que esto sea más explícita acaba de hacer
lst[:] = [v for v in lst if pred(v)]
Yo no creo que vaya a hacer mucha diferencia en este caso, en términos de eficiencia.
Cualquiera de estos dos últimos enfoques, si entiendo correctamente cómo funcionan realmente, hacer una copia extra de la lista, por lo que una de las soluciones de buena fe in situ mencionadas anteriormente sería mejor si se trata de algunas "grandes extensiones de tierra".
'enumerate' parece ajustar los índices de forma apropiada. No pensé que fuera así hasta que lo intenté. Escriba un bucle simple sobre una lista del 1 al 20 que elimine cada elemento que sea un múltiplo par de 3. Imprima la lista y el índice cada vez que realice una eliminación. Eliminará los índices 2, 4, 5, 6, 10 y 12. –
Puede simplificar el ciclo haciendo un bucle sobre él al revés. Luego, cuando eliminas un elemento, no tienes que decrementar (o incluso tener) 'end'. Además, no hay rama en el tiempo. – aaronasterling
@ D.Shawley: O estás confundido o lo estoy. Escribí algunos [doctests] (http://gist.github.com/618883) para probar las diversas soluciones presentadas a esta pregunta; tal vez tengo algo mal con eso? – intuited
Usaría una expresión de generador sobre una lista de comprensión para evitar una lista potencialmente grande e intermedia.
result = (x for x in l if f(x))
# print it, or something
print list(result)
Al igual que una lista por comprensión, esto no va a modificar la lista original, en su lugar.
>>> s = [1, 2, 3, 4, 5, 6]
>>> def f(x):
... if x<=2: return 0
... else: return 1
>>> for n,x in enumerate(s):
... if f(x) == 0: s[n]=None
>>> s=filter(None,s)
>>> s
[3, 4, 5, 6]
Esto no funciona: para la lista '[1, 2, 3, 4, 5, 6]' y 'f = lambda v: v <= 2' obtengo' [1, 2, 4, 6] ' . – intuited
Con una expresión generadora:
alist[:] = (item for item in alist if afunction(item))
Funcional:
alist[:] = filter(afunction, alist)
o:
import itertools
alist[:] = itertools.ifilter(afunction, alist)
Todos equivalente.
También puede utilizar una lista de comprensión:
alist = [item for item in alist if afunction(item)]
una actualización in situ modificación:
import collections
indexes_to_delete= collections.deque(
idx
for idx, item in enumerate(alist)
if afunction(item))
while indexes_to_delete:
del alist[indexes_to_delete.pop()]
- 1. Eliminar todos los elementos de una lista
- 2. todos los elementos en una lista
- 3. ¿Cómo eliminar todos los elementos nulos dentro de una lista genérica de una vez?
- 4. cuál es una buena manera de eliminar los últimos directorios
- 5. C# - Lista - eliminar todos los elementos pero NO los primeros
- 6. ¿Cuál es la manera más rápida de filtrar una lista de cadenas al hacer una lista de Intellisense/Autocomplete?
- 7. Rails 3 eliminar todos los elementos de una matriz
- 8. Python: eliminar muchos elementos de una lista
- 9. ¿Qué es una buena manera de generar una lista infinita de todos los enteros en Haskell
- 10. Eliminar todos los elementos del diccionario cuya clave es un elemento de una lista
- 11. Eliminar elementos de una lista que contiene caracteres específicos
- 12. Seleccionar todos los elementos de una lista en hibernación
- 13. ¿La mejor manera de eliminar todos los elementos de una matriz de ActionScript?
- 14. ¿Cómo comprobar si todos los elementos de una lista coinciden con una condición?
- 15. cómo eliminar todos los elementos en una tabla de Lua?
- 16. Eliminar elementos de una lista anidada Python
- 17. Strip todos los elementos de una lista de cadenas
- 18. scala Eliminar (en su lugar) todos los elementos de un ListBuffer que cumplan con una condición
- 19. Eliminar elementos de una lista en otra
- 20. Prolog eliminar elementos múltiples de una lista
- 21. ¿Cómo mostrar todos los elementos en una lista de arrays?
- 22. ¿Cuál es la forma más pitónica de garantizar que todos los elementos de una lista sean diferentes?
- 23. ¿Cómo eliminar varios elementos de una lista?
- 24. Eliminar todos los elementos de una lista <T> si ocurren variaciones de T
- 25. Comprobando si todos los elementos en una lista son únicos
- 26. ¿Cuál es la forma más eficiente de eliminar todos los elementos de una matriz de otra matriz?
- 27. Dar formato a todos los elementos de una lista
- 28. Coldfusion: ¿elimina todos los valores no numéricos de una lista?
- 29. Hibernar: la mejor manera de eliminar elementos en una colección
- 30. Cómo crear/eliminar varios elementos en una transacción
Tenga en cuenta que esto crea una nueva lista; no muta una lista existente. – intuited
'if not fn (x)' es más idiomático y funciona correctamente con cualquier valor que Python considere verdadero/falso (su función da por resultado 0 o 1, pero no hay ninguna razón para codificar esta suposición). –