2015-08-30 29 views
12

ho un elenco di gruppi:rimozione duplicati di un elenco di gruppi

L = [set([1, 4]), set([1, 4]), set([1, 2]), set([1, 2]), set([2, 4]), set([2, 4]), set([5, 6]), set([5, 6]), set([3, 6]), set([3, 6]), set([3, 5]), set([3, 5])] 

(in realtà nel mio caso una conversione di una lista di tuple reciproci)

e voglio rimuovere i duplicati per ottenere :

L = [set([1, 4]), set([1, 2]), set([2, 4]), set([5, 6]), set([3, 6]), set([3, 5])] 

Ma se provo:

>>> list(set(L)) 
TypeError: unhashable type: 'set' 

O

>>> list(np.unique(L)) 
TypeError: cannot compare sets using cmp() 

Come ottengo un elenco di gruppi di insiemi distinti?

+0

Un modo potrebbe essere convertire l'elenco di 'set' in' list' di 'list' e quindi rimuovere i duplicati e quindi riconvertire gli elementi' list' in 'set'. – ZdaR

+0

@ ZdaR Dirò questo in grassetto: ** Il tuo suggerimento è sbagliato. ** Seguendo la parte delle tue istruzioni che dice "* converti la lista di' set' in 'lista' di' lista' e poi rimuovi the dupicates * ", otteniamo quella lista' (map (list, [{3, 11}, {11, 3}])) 'output' [[3, 11], [11, 3]] '. – ogogmad

risposta

16

Il modo migliore è quello di convertire i set a frozenset s (che sono hashable) e quindi utilizzare set per ottenere solo i set unici, come questo

>>> list(set(frozenset(item) for item in L)) 
[frozenset({2, 4}), 
frozenset({3, 6}), 
frozenset({1, 2}), 
frozenset({5, 6}), 
frozenset({1, 4}), 
frozenset({3, 5})] 

Se li volete come insiemi, allora si può convertirli di nuovo a set s come questo

>>> [set(item) for item in set(frozenset(item) for item in L)] 
[{2, 4}, {3, 6}, {1, 2}, {5, 6}, {1, 4}, {3, 5}] 

Se si desidera che l'ordine anche di mantenere, durante la rimozione dei duplicati, quindi è possibile utilizzare collections.OrderedDict, come questo

>>> from collections import OrderedDict 
>>> [set(i) for i in OrderedDict.fromkeys(frozenset(item) for item in L)] 
[{1, 4}, {1, 2}, {2, 4}, {5, 6}, {3, 6}, {3, 5}] 
+0

@ PM2Ring Esiste in 2.7 cosicché quell'istruzione non sia strettamente vera. –

+0

@DanD: Oops! Inizialmente ho guardato i [Python 3 docs] (https://docs.python.org/3/library/collections.html#collections.OrderedDict), dove dice "New in version 3.1". Ma ho appena controllato i documenti di Python 2 e dice "Novità nella versione 2.7."; Avrei dovuto controllare lì per vedere se era stato backportato. Mi dispiace per quello Toglierò il mio commento (i). –

2

Un'alternativa utilizzando un ciclo:

result = list() 
for item in L: 
    if item not in result: 
     result.append(item) 
+1

È meglio usare '[]' di 'list()' per creare una lista –

+0

Perché Bhargav Rao? –

+1

@ReblochonMasque: è perché '[]' è la sintassi letterale (che consente di creare un'istanza della lista vuota in fase di compilazione) mentre 'list()' è una chiamata di funzione (il nome della funzione deve essere cercato in fase di esecuzione e quindi chiamato a restituire la lista vuota). Quest'ultimo è leggermente più costoso. –

1

Ecco un'altra alternativa

yourNewSet = map(set,list(set(map(tuple,yourSet)))) 
+0

** Questa risposta è sbagliata **. Due set uguali possono essere associati a due tuple differenti. Ho visto accadere questo. Ad esempio: 'ss = [{3, 11}, {11, 3}]; list (map (tuple, ss)) 'output' [(3, 11), (11, 3)] ' – ogogmad

0

C'è un'altra alternativa.

import itertools 
list_sets = [set(['a', 'e', 'f']), set(['c', 'b', 'f']), set(['a', 'e', 'f']), set(['a', 'd']), set(['a', 'e', 'f'])] 

lists = [list(s) for s in list_sets] # convert a list of sets to a list of lists 
lists.sort() 
lists_remove_duplicates = [lists for lists,_ in itertools.groupby(lists)] 
print(lists_remove_duplicates) 

# output 
[['a', 'd'], ['a', 'e', 'f'], ['c', 'b', 'f']]