Tengo una lista de dictados, y me gustaría eliminar los dictados con pares idénticos de clave y valor.
Para esta lista: [{'a': 123}, {'b': 123}, {'a': 123}]
Quisiera regresar esto: [{'a': 123}, {'b': 123}]
Otro ejemplo:
Para esta lista: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}, {'a': 123, 'b': 1234}]
Quisiera regresar esto: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}]
python
list
dictionary
Brenden
fuente
fuente
set()
Respuestas:
Prueba esto:
La estrategia es convertir la lista de diccionarios en una lista de tuplas donde las tuplas contienen los elementos del diccionario. Dado que las tuplas se pueden dividir en hash, puede eliminar duplicados usando
set
(usando una comprensión establecida aquí, la alternativa más antigua de Python seríaset(tuple(d.items()) for d in l)
) y, después de eso, volver a crear los diccionarios a partir de tuplas condict
.dónde:
l
es la lista originald
es uno de los diccionarios en la listat
es una de las tuplas creadas a partir de un diccionarioEditar: si desea conservar el pedido, la línea anterior no funcionará, ya
set
que no lo hará. Sin embargo, con algunas líneas de código, también puede hacer eso:Salida de ejemplo:
Nota: Como señaló @alexis, puede suceder que dos diccionarios con las mismas claves y valores no generen la misma tupla. Eso podría suceder si pasan por un historial diferente de agregar / quitar claves. Si ese es el caso de su problema, considere ordenar
d.items()
como él sugiere.fuente
d.items()
no se garantiza que devuelva elementos en un orden particular. Debe hacertuple(sorted(d.items()))
para asegurarse de no obtener diferentes tuplas para los mismos pares clave-valor.json
módulo como lo hice yoOtra frase basada en la comprensión de la lista:
Aquí, dado que podemos usar la
dict
comparación, solo conservamos los elementos que no están en el resto de la lista inicial (esta noción solo es accesible a través del índicen
, de ahí el uso deenumerate
).fuente
if i not in d[n + 1:]
itera sobre la lista completa de dictados (den
pero que solo reduce a la mitad el número total de operaciones) y está haciendo esa verificación para cada elemento en su diccionario, por lo que este código es O (n ^ 2) complejidad de tiempoOtras respuestas no funcionarían si está operando en diccionarios anidados, como objetos JSON deserializados. Para este caso puedes usar:
fuente
Si usar un paquete de terceros estaría bien, entonces podría usar
iteration_utilities.unique_everseen
:Conserva el orden de la lista original y ut también puede manejar elementos no compartibles como los diccionarios recurriendo a un algoritmo más lento (
O(n*m)
donden
están los elementos en la lista original ym
los elementos únicos en la lista original en lugar deO(n)
). En caso de que tanto las claves como los valores sean hashables, puede usar elkey
argumento de esa función para crear elementos hashaable para la "prueba de unicidad" (para que funcioneO(n)
).En el caso de un diccionario (que se compara independientemente del orden), debe asignarlo a otra estructura de datos que se compare así, por ejemplo
frozenset
:Tenga en cuenta que no debe usar un
tuple
enfoque simple (sin ordenar) porque los diccionarios iguales no necesariamente tienen el mismo orden (incluso en Python 3.7, donde se garantiza el orden de inserción , no el orden absoluto):E incluso ordenar la tupla podría no funcionar si las teclas no se pueden ordenar:
Punto de referencia
Pensé que podría ser útil ver cómo se compara el rendimiento de estos enfoques, así que hice un pequeño punto de referencia. Los gráficos de referencia son el tiempo frente al tamaño de la lista basado en una lista que no contiene duplicados (que se eligió arbitrariamente, el tiempo de ejecución no cambia significativamente si agrego algunos o muchos duplicados). Es un diagrama de registro de registro, por lo que se cubre el rango completo.
Los tiempos absolutos:
Los tiempos relativos al enfoque más rápido:
El segundo enfoque de thefourtheye es más rápido aquí. El
unique_everseen
enfoque con lakey
función está en el segundo lugar, sin embargo, es el enfoque más rápido que conserva el orden. Los otros enfoques de jcollado y thefourtheye son casi tan rápido. El enfoque que usaunique_everseen
sin clave y las soluciones de Emmanuel y Scorpil son muy lentas para listas más largas y se comportan mucho peor enO(n*n)
lugar deO(n)
. El enfoque de stpk conjson
no esO(n*n)
pero es mucho más lento que losO(n)
enfoques similares .El código para reproducir los puntos de referencia:
Para completar, aquí está el momento para una lista que contiene solo duplicados:
Los tiempos no cambian significativamente, excepto
unique_everseen
sin lakey
función, que en este caso es la solución más rápida. Sin embargo, ese es el mejor caso (por lo que no es representativo) para esa función con valores no compartibles porque su tiempo de ejecución depende de la cantidad de valores únicos en la lista:O(n*m)
que en este caso es solo 1 y, por lo tanto, se ejecutaO(n)
.Descargo de responsabilidad: soy el autor de
iteration_utilities
.fuente
A veces, los bucles antiguos siguen siendo útiles. Este código es un poco más largo que el de jcollado, pero muy fácil de leer:
fuente
0
enrange(0, len(a))
que no es necesario.Si desea preservar la orden, puede hacerlo
Si el orden no importa, entonces puedes hacerlo
fuente
dict_values
salida no serializable en lugar de una lista. Tienes que volver a incluir todo en una lista.list(frozen.....)
Si está utilizando Pandas en su flujo de trabajo, una opción es alimentar una lista de diccionarios directamente al
pd.DataFrame
constructor. Luego usedrop_duplicates
yto_dict
métodos para el resultado requerido.fuente
No es una respuesta universal , pero si su lista está ordenada por alguna clave, como esta:
entonces la solución es tan simple como:
Resultado:
Funciona con diccionarios anidados y (obviamente) conserva el orden.
fuente
Puede usar un conjunto, pero debe convertir los dictos en un tipo hashable.
Único ahora es igual
Para recuperar los dictados:
fuente
d.iteritems()
no está garantizado, por lo que puede terminar con 'duplicados'unique
.Aquí hay una solución rápida de una línea con una comprensión de lista doblemente anidada (basada en la solución de @Emmanuel).
Esto usa una sola clave (por ejemplo
a
) en cada dict como clave principal, en lugar de verificar si la dict completa coincideNo es lo que OP solicitó, pero es lo que me trajo a este hilo, así que pensé que publicaría la solución con la que terminé
fuente
No tan corto pero fácil de leer:
Ahora, la lista
list_of_data_uniq
tendrá dictados únicos.fuente