Supongamos que tengo dos diccionarios de Python, dictA
y dictB
. Necesito averiguar si hay claves que están presentes dictB
pero no en dictA
. ¿Cuál es la forma más rápida de hacerlo?
¿Debo convertir las claves del diccionario en un conjunto y luego continuar?
Interesado en conocer tus pensamientos ...
Gracias por sus respuestas
Disculpas por no decir mi pregunta correctamente. Mi situación es la siguiente: tengo una dictA
que puede ser igual dictB
o puede que falten algunas claves en comparación dictB
o, de lo contrario, el valor de algunas claves puede ser diferente, lo que debe establecerse en dictA
el valor de la clave.
El problema es que el diccionario no tiene un estándar y puede tener valores que pueden ser dict de dict.
Decir
dictA={'key1':a, 'key2':b, 'key3':{'key11':cc, 'key12':dd}, 'key4':{'key111':{....}}}
dictB={'key1':a, 'key2:':newb, 'key3':{'key11':cc, 'key12':newdd, 'key13':ee}.......
Por lo tanto, el valor 'clave2' debe restablecerse al nuevo valor y 'clave13' debe agregarse dentro del dict. El valor clave no tiene un formato fijo. Puede ser un valor simple o un dict o un dict de dict.
fuente
def update(self, new_dict): self.__init__(new_dict, self.current_dict)
o similar para que pueda hacer una comparación continuaDictDiffer
clase es una clase sin estado y podría ser una función. Los valoreschanged
yunchanged
podrían calcularse en el mismo bucle. Estas dos funciones podrían devolver una enlist
lugar de unaset
que ciertamente es menos costosa. Para una comparación profunda, puede echar un vistazo al marco de prueba de la Unidad: docs.python.org/2/library/unittest.html , solo siga elassertDictEqual
método en el código fuente.set(dictb)
es probablemente mejor queset(dictb.keys())
.En caso de que desee la diferencia de forma recursiva, he escrito un paquete para python: https://github.com/seperman/deepdiff
Instalación
Instalar desde PyPi:
Ejemplo de uso
Importador
El mismo objeto vuelve vacío
El tipo de un artículo ha cambiado
El valor de un artículo ha cambiado
Artículo agregado y / o eliminado
Diferencia de cadena
Diferencia de cuerda 2
Cambio de tipo
Lista de diferencia
Lista de diferencia 2:
Enumere la diferencia ignorando el orden o los duplicados: (con los mismos diccionarios que arriba)
Lista que contiene el diccionario:
Conjuntos
Tuplas nombradas:
Objetos personalizados:
Atributo de objeto agregado:
fuente
ignore_order=True
. Puede encontrar los documentos en deepdiff.readthedocs.io/en/latest/diff.htmlno estoy seguro de si es "rápido" o no, pero normalmente, uno puede hacer esto
fuente
dicta
ydictb
ya que él quiere saber esas clavesdictb
no están ahídicta
.for key in dicta.keys():
=>for key in dicta:
Como escribió Alex Martelli, si simplemente desea verificar si alguna tecla en B no está en A, ese
any(True for k in dictB if k not in dictA)
sería el camino a seguir.Para encontrar las claves que faltan:
Entonces esas dos soluciones son más o menos la misma velocidad.
fuente
any(k not in dictA for k in dictB)
Si realmente quiere decir exactamente lo que dice (que solo necesita averiguar SI "hay claves" en B y no en A, y NO CUÁLES podrían ser esas), la forma más rápida debería ser:
Si realmente necesita averiguar QUÉ LLAVES, si las hay, están en B y no en A, y no solo "SI" hay tales llaves, entonces las respuestas existentes son bastante apropiadas (pero sugiero más precisión en futuras preguntas si eso es así) de hecho lo que quieres decir ;-).
fuente
Uso
set()
:fuente
set(d)
ya devuelve solo las teclas, así que puede hacerloset(da).intersection(db)
La respuesta principal de hughdbrown sugiere usar la diferencia establecida, que definitivamente es el mejor enfoque:
El problema con este código es que crea dos listas solo para crear dos conjuntos, por lo que está desperdiciando 4N de tiempo y 2N de espacio. También es un poco más complicado de lo que debe ser.
Por lo general, esto no es un gran problema, pero si lo es:
collections.abc.Mapping
tiene unKeysView
que actúa como aSet
.Python 2
En Python 2,
keys()
devuelve una lista de las claves, no aKeysView
. Entonces tienes que pedirloviewkeys()
directamente.Para el código 2.7 / 3.x de la versión dual, es de esperar que esté usando
six
o algo similar, por lo que puede usarsix.viewkeys(dictb)
:En 2.4-2.6, no hay
KeysView
. Pero al menos puede reducir el costo de 4N a N construyendo su conjunto izquierdo directamente desde un iterador, en lugar de crear primero una lista:Artículos
Así que realmente no necesita comparar las claves, sino los elementos. An
ItemsView
es solo aSet
si los valores son hashables, como las cadenas. Si lo son, es fácil:Dif recursivo
Aunque la pregunta no es pedir directamente una diferencia recursiva, algunos de los valores de ejemplo son dictados, y parece que la salida esperada los difiere recursivamente. Ya hay varias respuestas aquí que muestran cómo hacerlo.
fuente
Hay otra pregunta en stackoverflow sobre este argumento y tengo que admitir que hay una solución simple explicada: la biblioteca datadiff de python ayuda a imprimir la diferencia entre dos diccionarios.
fuente
Aquí hay una manera que funcionará, permite claves que evalúan
False
y aún utiliza una expresión generadora para caerse temprano si es posible. Sin embargo, no es excepcionalmente bonito.EDITAR:
THC4k publicó una respuesta a mi comentario en otra respuesta. Aquí hay una forma mejor y más bonita de hacer lo anterior:
No estoy seguro de cómo eso nunca se me pasó por la cabeza ...
fuente
any(k for k in dictB if k not in dictA)
que no es lo mismo (para las llaves falsey). Verifique el historial de edición / marcas de tiempo.Esta es una pregunta antigua y hace un poco menos de lo que necesitaba, por lo que esta respuesta realmente resuelve más de lo que pregunta. Las respuestas en esta pregunta me ayudaron a resolver lo siguiente:
Todo esto combinado con JSON lo convierte en un soporte de almacenamiento de configuración bastante potente.
La solución ( también en github ):
fuente
¿Qué pasa con standart (comparar objeto completo)
PyDev-> nuevo Módulo PyDev-> Módulo: unittest
fuente
Si en Python ≥ 2.7:
fuente
Aquí hay una solución para comparar en profundidad 2 claves de diccionarios:
fuente
Aquí hay una solución que puede comparar más de dos dictados:
ejemplo de uso:
fuente
Mi receta de diferencia simétrica entre dos diccionarios:
Y el resultado es:
fuente
Como se mencionó en otras respuestas, unittest produce una buena salida para comparar dictos, pero en este ejemplo no queremos tener que construir primero una prueba completa.
Al eliminar la fuente de prueba de la unidad, parece que puede obtener una solución justa con solo esto:
entonces
Resultados en:
Dónde:
Al igual que en unittest, la única advertencia es que el mapeo final puede considerarse como una diferencia, debido a la coma / corchete final.
fuente
@Maxx tiene una excelente respuesta, use las
unittest
herramientas proporcionadas por Python:Luego, en cualquier parte de su código puede llamar:
El resultado resultante se parece al resultado
diff
, imprimiendo bonitos los diccionarios con+
o-
anteponiendo cada línea que es diferente.fuente
No estoy seguro de si todavía es relevante, pero me encontré con este problema, mi situación solo necesitaba devolver un diccionario de los cambios para todos los diccionarios anidados, etc. No pude encontrar una buena solución, pero terminé escribiendo una función simple para hacer esto . Espero que esto ayude,
fuente
Si desea una solución integrada para una comparación completa con estructuras de dict arbitrarias, la respuesta de @ Maxx es un buen comienzo.
fuente
Basado en la respuesta de ghostdog74,
imprimirá un valor diferente de dicta
fuente
Intente esto para encontrar la intersección, las teclas que están en ambas direcciones, si desea que las llaves no se encuentren en la segunda memoria, simplemente use el no en ...
fuente