Pregunta ¿Eliminar todos los valores dentro de una lista de otra lista? [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Estoy buscando una forma de eliminar todos los valores dentro de una lista de otra lista.

Algo como esto:

a = range(1,10)  
a.remove([2,3,7])  
print a  
a = [1,4,5,6,8,9]  

75
2018-03-25 11:20


origen


Respuestas:


>>> a = range(1, 10)
>>> [x for x in a if x not in [2, 3, 7]]
[1, 4, 5, 6, 8, 9]

101
2018-03-25 11:22



Si no tiene valores repetidos, puede usar establecer la diferencia.

x = set(range(10))
y = x - set([2, 3, 7])
# y = set([0, 1, 4, 5, 6, 8, 9])

y luego convertir de nuevo a la lista, si es necesario.


32
2018-03-29 18:57



Estaba buscando una forma rápida de hacer el tema, así que hice algunos experimentos con las formas sugeridas. Y me sorprendieron los resultados, así que quiero compartirlo contigo.

Los experimentos fueron hechos usando pythonbenchmark herramienta y con

a = range(1,50000) # Source list
b = range(1,15000) # Items to remove

Resultados:

 def comprehension(a, b):
     return [x for x in a if x not in b]

5 intentos, tiempo promedio 12.8 segundos

def filter_function(a, b):
    return filter(lambda x: x not in b, a)

5 intentos, tiempo promedio 12.6 segundos

def modification(a,b):
    for x in b:
        try:
            a.remove(x)
        except ValueError:
            pass
    return a

5 intentos, tiempo promedio 0.27 segundos

def set_approach(a,b):
    return list(set(a)-set(b))

5 intentos, tiempo promedio 0.0057 segundo

También hice otra medición con un tamaño de entrada más grande para las dos últimas funciones

a = range(1,500000)
b = range(1,100000)

Y los resultados:

Para modificación (método de eliminación): el tiempo promedio es de 252 segundos Para el enfoque conjunto, el tiempo promedio es 0.75 segundos

Entonces puedes ver que el enfoque con los conjuntos es significativamente más rápido que otros. Sí, no mantiene artículos similares, pero si no lo necesita, es para usted. Y casi no hay diferencia entre la comprensión de la lista y el uso de la función de filtro. Usar 'eliminar' es ~ 50 veces más rápido, pero modifica la lista de fuentes. Y la mejor opción es usar sets: ¡es más de 1000 veces más rápido que la comprensión de listas!


18
2018-05-20 15:16



a = range(1,10)
itemsToRemove = set([2, 3, 7])
b = filter(lambda x: x not in itemsToRemove, a)

o

b = [x for x in a if x not in itemsToRemove]

No crees el conjunto dentro del lambda o dentro de la comprensión. Si lo haces, será recreado en cada iteración, derrotando el punto de usar un conjunto.


11
2018-03-25 11:26



Otros han sugerido formas de hacer una nueva lista después de filtrar, p.

newl = [x for x in l if x not in [2,3,7]]

o

newl = filter(lambda x: x not in [2,3,7], l) 

pero a partir de su pregunta parece que desea una modificación in situ para que pueda hacer esto, esto también será mucho más rápido si la lista original es larga y los elementos a eliminar menos

l = range(1,10)
for o in set([2,3,7,11]):
    try:
        l.remove(o)
    except ValueError:
        pass

print l

salida:     [1, 4, 5, 6, 8, 9]

Estoy comprobando la excepción ValueError para que funcione incluso si los elementos no están en la lista original.

Además, si no necesita solución de modificación in situ por S.Mark es mas simple


5
2018-03-25 11:38



La forma más simple es

>>> a = range(1, 10)
>>> for x in [2, 3, 7]:
...  a.remove(x)
... 
>>> a
[1, 4, 5, 6, 8, 9]

Un posible problema aquí es que cada vez que llame a remove (), todos los elementos se mezclan en la lista para llenar el agujero. Así que si a crece muy grande, esto terminará siendo bastante lento.

De esta forma se crea una lista completamente nueva. La ventaja es que evitamos todo el barajado del primer enfoque

>>> removeset = set([2, 3, 7])
>>> a = [x for x in a if x not in removeset]

Si quieres modificar a en su lugar, solo se requiere un pequeño cambio

>>> removeset = set([2, 3, 7])
>>> a[:] = [x for x in a if x not in removeset]

5
2018-03-25 11:40



>>> a=range(1,10)
>>> for i in [2,3,7]: a.remove(i)
...
>>> a
[1, 4, 5, 6, 8, 9]

>>> a=range(1,10)
>>> b=map(a.remove,[2,3,7])
>>> a
[1, 4, 5, 6, 8, 9]

4
2018-03-25 11:43