2012-05-11 24 views
10

¿Cómo eliminar elementos duplicados de una lista usando la lista de comprensión? Tengo el siguiente código:¿Cómo eliminar elementos duplicados de una lista usando la lista de comprensión?

a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8] 
b = [] 
b = [item for item in a if item not in b] 

pero no funciona, solo produce una lista idéntica. ¿Por qué está produciendo una lista idéntica?

+4

Porque 'b' está vacío en el momento en que ejecuta' si el elemento no está en b'. La lista de comprensión se realiza en la memoria y el resultado se asigna a 'b' al final. –

+0

posible duplicado de [Algoritmo - ¿Cómo eliminar elementos duplicados en una lista de manera eficiente?] (Http://stackoverflow.com/questions/1801459/algorithm-how-to-delete-duplicate-elements-in-a-list-efficiently) –

+0

Eso significa que la comprensión de la lista no funciona como un bucle? – Alinwndrld

Respuesta

13

Se está produciendo una lista idéntica como b no contiene elementos en tiempo de ejecución. Lo que se desea es la siguiente:

>>> a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8] 
>>> b = [] 
>>> [b.append(item) for item in a if item not in b] 
[None, None, None, None, None, None, None, None] 
>>> b 
[1, 2, 3, 5, 9, 6, 8, 7] 
+14

Tenga cuidado con el uso [la lista de comprensión de los efectos secundarios] (http://stackoverflow.com/q/5753597/566644). Use un bucle for para uso regular. –

7

Si no les importa usar una técnica diferente a la comprensión de lista se puede utilizar un conjunto para que:

>>> a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8] 
>>> b = list(set(a)) 
>>> print b 
[1, 2, 3, 5, 6, 7, 8, 9] 
+0

He visto la función de conjunto, solo quiero saber qué hay de malo con el código anterior y si podría corregirse? – Alinwndrld

+2

conjunto no mantendrá el orden inicial ... así que simplemente tenga en cuenta que –

3

Uso keys en un dict construida con valores en a como sus claves.

b = dict([(i, 1) for i in a]).keys() 

O utilizar un conjunto:

b = [i for i in set(a)] 
4

La razón de que la lista no ha cambiado es que b comienza vacío. Esto significa que if item not in b es siempre True. Solo después de que se haya generado la lista, está esta nueva lista no vacía asignada a la variable b.

+1

Si lo entiendo correctamente, eso significa que la comprensión de la lista agrega elementos de una sola vez en lugar de verificar y agregar cada elemento de a uno por vez, como en el ciclo. – Alinwndrld

+1

@Alinwndrld: No creo que sea una conclusión válida. Solo significa que la lista de comprensión se evalúa antes de la tarea. La lista puede estar construida en un bucle internamente. –

2

Uso groupby:

>>> from itertools import groupby 
>>> a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8] 
>>> [k for k, _ in groupby(sorted(a, key=lambda x: a.index(x)))] 
[1, 2, 3, 5, 9, 6, 8, 7] 

dejar de lado el argumento clave si no se preocupan por la que ordenar el valor apareció por primera vez en la lista original, por ejemplo,

>>> [k for k, _ in groupby(sorted(a))] 
[1, 2, 3, 5, 6, 7, 8, 9] 

Puede hacer algunas cosas interesantes con groupby. Para identificar los elementos que aparecen varias veces:

>>> [k for k, v in groupby(sorted(a)) if len(list(v)) > 1] 
[2, 3, 5, 8] 

O para construir un diccionario de frecuencia:

>>> {k: len(list(v)) for k, v in groupby(sorted(a))} 
{1: 1, 2: 3, 3: 4, 5: 4, 6: 1, 7: 1, 8: 2, 9: 1} 

Hay algunas funciones muy útiles en el módulo itertools: chain, tee y product para nombrar unos pocos !

1
>>> a = [10,20,30,20,10,50,60,40,80,50,40,0,100,30,60] 
>>> [a.pop(a.index(i, a.index(i)+1)) for i in a if a.count(i) > 1] 
>>> print(a) 
Cuestiones relacionadas