2012-05-11 12 views
10

Come rimuovere elementi duplicati da un elenco utilizzando la comprensione di elenchi? Ho codice seguente:Come rimuovere elementi duplicati da una lista usando la comprensione delle liste?

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] 

ma non funziona, solo produce elenco identico. Perché produce un elenco identico?

+4

Poiché 'b' è vuoto nel momento in cui si esegue' se l'elemento non è in b'. La comprensione delle liste viene eseguita in memoria e il risultato viene assegnato a 'b' alla fine. –

+0

possibile duplicato di [Algoritmo - Come eliminare in modo efficiente gli elementi duplicati in un elenco?] (Http://stackoverflow.com/questions/1801459/algorithm-how-to-delect-duplicate-elements-in-a-list-efficiently) –

+0

Ciò significa che la comprensione delle liste non funziona come il ciclo? – Alinwndrld

risposta

13

E 'produrre un elenco identico come b non contiene elementi in fase di esecuzione. Quello che ci si vuole in questo:

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

Attenzione all'utilizzo di [list comprehensions for side effects] (http://stackoverflow.com/q/5753597/566644). Utilizzare invece un ciclo for regolare. –

7

Se non ti dispiace utilizzando una tecnica diversa da quella di lista è possibile utilizzare un set per questo:

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

Ho visto la funzione set, voglio solo sapere cosa c'è che non va nel codice precedente e se può essere corretto? Il set – Alinwndrld

+2

non manterrà l'ordine iniziale ... quindi prendi nota di quello –

3

Usa keys su un dict costruita con valori in a come le sue chiavi.

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

Oppure utilizzare un set:

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

La ragione per cui la lista è immutata è che b inizia vuota. Ciò significa che if item not in b è sempre True. Solo dopo che la lista è stata generata è questa nuova lista non vuota assegnata alla variabile b.

+1

Se ho capito bene, significa che la comprensione delle liste aggiunge elementi in una volta sola invece di controllare e aggiungere ogni elemento uno alla volta come in loop. – Alinwndrld

+1

@Alinwndrld: Non penso che sia una conclusione valida. Significa solo che la comprensione della lista viene valutata prima dell'assegnazione. L'elenco potrebbe essere costruito internamente in un ciclo. –

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] 

lasciare fuori l'argomento chiave se non si preoccupano che ordinare il valore prima apparizione nella lista originale, per esempio

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

si possono fare alcune cose interessanti con groupby. Per identificare gli elementi che compaiono più volte:

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

o per costruire un dizionario di frequenza:

>>> {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} 

Ci sono alcune funzioni molto utili nel modulo itertools: chain, tee e product per citarne alcuni !

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) 
Problemi correlati