2012-10-04 13 views
14

La manera más conveniente, "Pythonic" para eliminar duplicados de una lista es básicamente:la eliminación de duplicados utilizando comparaciones personalizados

mylist = list(set(mylist)) 

Pero supongamos que su criterio para contar un duplicado depende de un campo miembro particular de los objetos contenidos en mylist.

Bueno, una solución es simplemente definir __eq____hash__ y de los objetos en mylist, y luego el clásico list(set(mylist)) va a funcionar.

Pero a veces tiene requisitos que requieren un poco más de flexibilidad. Sería muy conveniente poder crear lambdas sobre la marcha para usar rutinas de comparación personalizadas para identificar duplicados de diferentes maneras. Idealmente, algo así como:

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

Por supuesto, que en realidad no funciona porque el constructor set no toma una función de comparación, y set requiere llaves hashable también.

Entonces, ¿cuál es la forma más cercana de lograr algo así, para que pueda eliminar duplicados utilizando funciones de comparación arbitrarias?

Respuesta

19

Usted puede usar un diccionario en lugar de un conjunto, donde las claves de la dict serán los valores únicos:

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

Esa es la forma más fácil de hacerlo. Y el rendimiento debería ser casi igual al método establecido. – Chronial

+2

Wow, nunca antes había visto la sintaxis '{x.firstname: x for x in mylist}'. Cómo se llama y dónde puedo encontrarlo en los documentos. –

+2

@MarwanAlsabbagh: Es una [comprensión de dict] (http://www.python.org/dev/peps/pep-0274/). Fue agregado en Python 2.7 y 3.0. Es equivalente a 'dict ((x.firstname, x) para x en mylist)'. – interjay

0

Me gustaría hacer esto:

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

Si es necesario tener una mayor flexibilidad con el operador "en"

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) 
Cuestiones relacionadas