2012-10-04 8 views
14

Il modo più conveniente "Pythonic" per rimuovere i duplicati da una lista è fondamentalmente:rimuovendo i duplicati che utilizzano i confronti personalizzati

mylist = list(set(mylist)) 

Ma supponiamo che i tuoi criteri per il conteggio di un duplicato dipende da un particolare campo membro degli oggetti contenuti in mylist.

Beh, una soluzione è quella di definire solo __eq__ e __hash__ per gli oggetti in mylist, e poi il classico list(set(mylist)) funzionerà.

Ma a volte ci sono requisiti che richiedono un po 'più di flessibilità. Sarebbe molto comodo poter creare on-the-fly lambdas per utilizzare routine di confronto personalizzate per identificare i duplicati in modi diversi. Idealmente, qualcosa come:

mylist = list(set(mylist, key = lambda x: x.firstname)) 

Naturalmente, che in realtà non funziona perché il costruttore set non ci vuole un funzione di confronto, e set richiede chiavi hashable pure.

Quindi qual è il modo più vicino per ottenere qualcosa del genere, in modo da poter rimuovere i duplicati utilizzando funzioni di confronto arbitrarie?

risposta

19

è possibile utilizzare un dict invece di un set, in cui le chiavi del dict saranno i valori unici:

d = {x.firstname: x for x in mylist} 
mylist = list(d.values()) 
+0

Questo è il modo generalmente più semplice per procedere con questo. E le prestazioni dovrebbero essere quasi uguali al metodo impostato. – Chronial

+2

Wow Non ho mai visto la sintassi '{x.firstname: x per x in mylist}' prima. Come si chiama e dove posso trovarlo nei documenti. –

+2

@MarwanAlsabbagh: È una [dict comprehension] (http://www.python.org/dev/peps/pep-0274/). E 'stato aggiunto in Python 2.7 e 3.0. È equivalente a 'dict ((x.firstname, x) per x in mylist)'. – interjay

0

farei questo:

duplicates = set() 
newlist = [] 
for item in mylist: 
    if item.firstname not in duplicates: 
     newlist.append(item) 
     excludes.add(item.firstname) 
0

Se avete bisogno di avere una maggiore flessibilità con operatore "in"

def is_in(value, value_list, comparer_function): 
    """ checkes whether "value" already in "value_list" """ 
    for vi in value_list: 
     if comparer_function(vi, value): 
      return True 
    return False 

def make_unique_set(in_list, comparer_function=lambda a, b: a == b): 
    """ retusn unique set of "in_list" """ 
    new_list = [] 
    for i in in_list: 
     if not is_in(i, new_list, comparer_function): 
      new_list.append(i) 
    return new_list 

make_unique_set(mylist, comparer_function=lambda a, b : a.firstname == b.firstname) 
Problemi correlati