Eliminar duplicados de diccionarios nesteds en la lista

Pregunta rápida y muy básica para principiantes.

Si tengo una lista de diccionarios parecidos a esto:

L = [] L.append({"value1": value1, "value2": value2, "value3": value3, "value4": value4}) 

Digamos que existen varias entradas donde value3 y value4 son idénticos a otros diccionarios nesteds. ¿Cómo puedo encontrar y eliminar rápida y fácilmente esos diccionarios duplicados?

Conservar el orden no tiene importancia.

Gracias.

EDITAR:

Si hay cinco entradas, así:

 L = [{"value1": fssd, "value2": dsfds, "value3": abcd, "value4": gk}, {"value1": asdasd, "value2": asdas, "value3": dafdd, "value4": sdfsdf}, {"value1": sdfsf, "value2": sdfsdf, "value3": abcd, "value4": gk}, {"value1": asddas, "value2": asdsa, "value3": abcd, "value4": gk}, {"value1": asdasd, "value2": dskksks, "value3": ldlsld, "value4": sdlsld}] 

La salida debería verse así:

 L = [{"value1": fssd, "value2": dsfds, "value3": abcd, "value4": gk}, {"value1": asdasd, "value2": asdas, "value3": dafdd, "value4": sdfsdf}, {"value1": asdasd, "value2": dskksks, "value3": ldlsld, "value4": sdlsld} 

En Python 2.6 o 3. *:

 import itertools import pprint L = [{"value1": "fssd", "value2": "dsfds", "value3": "abcd", "value4": "gk"}, {"value1": "asdasd", "value2": "asdas", "value3": "dafdd", "value4": "sdfsdf"}, {"value1": "sdfsf", "value2": "sdfsdf", "value3": "abcd", "value4": "gk"}, {"value1": "asddas", "value2": "asdsa", "value3": "abcd", "value4": "gk"}, {"value1": "asdasd", "value2": "dskksks", "value3": "ldlsld", "value4": "sdlsld"}] getvals = operator.itemgetter('value3', 'value4') L.sort(key=getvals) result = [] for k, g in itertools.groupby(L, getvals): result.append(g.next()) L[:] = result pprint.pprint(L) 

Casi lo mismo en Python 2.5, excepto que tienes que usar g.next () en lugar de next (g) en el apéndice.

Aquí hay una forma:

 keyfunc = lambda d: (d['value3'], d['value4']) from itertools import groupby giter = groupby(sorted(L, key=keyfunc), keyfunc) L2 = [g[1].next() for g in giter] print L2 

Puede utilizar una matriz temporal para almacenar un elemento dict. El código anterior tenía errores para eliminar elementos en el bucle for.

 (v,r) = ([],[]) for i in l: if ('value4', i['value4']) not in v and ('value3', i['value3']) not in v: r.append(i) v.extend(i.items()) l = r 

Su prueba:

 l = [{"value1": 'fssd', "value2": 'dsfds', "value3": 'abcd', "value4": 'gk'}, {"value1": 'asdasd', "value2": 'asdas', "value3": 'dafdd', "value4": 'sdfsdf'}, {"value1": 'sdfsf', "value2": 'sdfsdf', "value3": 'abcd', "value4": 'gk'}, {"value1": 'asddas', "value2": 'asdsa', "value3": 'abcd', "value4": 'gk'}, {"value1": 'asdasd', "value2": 'dskksks', "value3": 'ldlsld', "value4": 'sdlsld'}] 

ouputs

 {'value4': 'gk', 'value3': 'abcd', 'value2': 'dsfds', 'value1': 'fssd'} {'value4': 'sdfsdf', 'value3': 'dafdd', 'value2': 'asdas', 'value1': 'asdasd'} {'value4': 'sdlsld', 'value3': 'ldlsld', 'value2': 'dskksks', 'value1': 'asdasd'} 
 for dic in list: for anotherdic in list: if dic != anotherdic: if dic["value3"] == anotherdic["value3"] or dic["value4"] == anotherdic["value4"]: list.remove(anotherdic) 

Probado con

 list = [{"value1": 'fssd', "value2": 'dsfds', "value3": 'abcd', "value4": 'gk'}, {"value1": 'asdasd', "value2": 'asdas', "value3": 'dafdd', "value4": 'sdfsdf'}, {"value1": 'sdfsf', "value2": 'sdfsdf', "value3": 'abcd', "value4": 'gk'}, {"value1": 'asddas', "value2": 'asdsa', "value3": 'abcd', "value4": 'gk'}, {"value1": 'asdasd', "value2": 'dskksks', "value3": 'ldlsld', "value4": 'sdlsld'}] 

funcionó bien para mí 🙂

Esa es una lista de un diccionario y, pero, asumiendo que hay más diccionarios en la lista l :

 l = [ldict for ldict in l if ldict.get("value3") != value3 or ldict.get("value4") != value4] 

¿Pero es eso lo que realmente quieres hacer? Quizás necesites refinar tu descripción.

Por cierto, no use la list como nombre ya que es el nombre de un Python incorporado.

EDITAR: Suponiendo que comenzó con una lista de diccionarios, en lugar de una lista de listas de 1 diccionario cada uno que debería funcionar con su ejemplo. No funcionaría si alguno de los valores fuera Ninguno, así que mejor que algo como:

 l = [ldict for ldict in l if not ( ("value3" in ldict and ldict["value3"] == value3) and ("value4" in ldict and ldict["value4"] == value4) )] 

Pero todavía parece una estructura de datos inusual.

EDIT: no hay necesidad de usar get explícitos.

Además, siempre hay compensaciones en soluciones. Sin más información y sin medir realmente, es difícil saber qué compromisos de desempeño son los más importantes para el problema. Pero, como dice Zen : “Lo simple es mejor que lo complejo”.

Si entiendo correctamente, desea descartar coincidencias que vienen más adelante en la lista original, pero no le importa el orden de la lista resultante, así que:

(Probado con 2.5.2)

 tempDict = {} for d in L[::-1]: tempDict[(d["value3"],d["value4"])] = d L[:] = tempDict.itervalues() tempDict = None