Comparar dos diccionarios y verificar cuántos pares (clave, valor) son iguales

246

Tengo dos diccionarios, pero para simplificar, tomaré estos dos:

>>> x = dict(a=1, b=2)
>>> y = dict(a=2, b=2)

Ahora, quiero comparar si cada key, valuepar xtiene el mismo valor correspondiente en y. Entonces escribí esto:

>>> for x_values, y_values in zip(x.iteritems(), y.iteritems()):
        if x_values == y_values:
            print 'Ok', x_values, y_values
        else:
            print 'Not', x_values, y_values

Y funciona desde un tuple se devuelve a y luego se compara para la igualdad.

Mis preguntas:

¿Es esto correcto? ¿Hay un mejor manera de hacer esto? Mejor no en velocidad, estoy hablando de la elegancia del código.

ACTUALIZACIÓN: Olvidé mencionar que tengo que verificar cuántos key, valuepares son iguales.

usuario225312
fuente
21
x == ydebe ser cierto de acuerdo con stackoverflow.com/a/5635309/186202
Natim
x == y debería ser cierto. Uno puede verificar rápidamente en REPL. Consulte: docs.python.org/2/library/stdtypes.html#mapping-types-dict
Vikrant

Respuestas:

179

Si desea saber cuántos valores coinciden en ambos diccionarios, debería haber dicho que :)

Tal vez algo como esto:

shared_items = {k: x[k] for k in x if k in y and x[k] == y[k]}
print len(shared_items)
mouad
fuente
1
El mismo error si hay un elemento de lista para la clave dict. Creo que cmp es una mejor manera de hacerlo a menos que me falte algo.
Mutante
@Mutant que es un problema diferente. No puede crear un diccionario con una listclave en primer lugar. x = {[1,2]: 2}fallará. La pregunta ya tiene validez dicts.
AnnanFay
@annan: mal, la pregunta es genérica. el ejemplo en la descripción de la pregunta ya tiene "dictados válidos". Si publico una nueva pregunta, con el mismo título, pero con un dict "inválido" diferente, alguien lo marcará como duplicado. Votación a favor.
ribamar
66
@ribamar la pregunta es "Comparar dos diccionarios [...]". El 'dict inválido' anterior con listclaves no es un código válido de python: las claves dict deben ser inmutables. Por lo tanto, no estás comparando diccionarios. Si intenta usar una lista como clave de diccionario, su código no se ejecutará. No tienes objetos para comparar. Esto es como escribir y x = dict(23\;dfg&^*$^%$^$%^)luego quejarse de que la comparación no funciona con el diccionario. Por supuesto que no funcionará. El comentario de Tim, por otro lado, es sobre mutable values, de ahí que haya dicho que estos son problemas diferentes.
AnnanFay
1
@MikeyE: setrequiere que los valores sean hashaable y dictrequiere que las claves sean hashaable. set(x.keys())siempre funcionará porque las claves deben ser hashaable, pero set(x.values())fallarán en los valores que no son hashaable.
Tim Tisdall
173

Lo que quieres hacer es simplemente x==y

Lo que haces no es una buena idea, porque no se supone que los elementos de un diccionario tengan ningún orden. Es posible que esté comparando [('a',1),('b',1)]con [('b',1), ('a',1)](mismos diccionarios, diferente orden).

Por ejemplo, mira esto:

>>> x = dict(a=2, b=2,c=3, d=4)
>>> x
{'a': 2, 'c': 3, 'b': 2, 'd': 4}
>>> y = dict(b=2,c=3, d=4)
>>> y
{'c': 3, 'b': 2, 'd': 4}
>>> zip(x.iteritems(), y.iteritems())
[(('a', 2), ('c', 3)), (('c', 3), ('b', 2)), (('b', 2), ('d', 4))]

La diferencia es solo un elemento, pero su algoritmo verá que todos los elementos son diferentes

Jochen Ritzel
fuente
@ THC4k, perdón por no mencionarlo. Pero tengo que verificar cuántos valores coinciden en ambos diccionarios.
user225312
Ok, entonces, según mi actualización, ¿mi forma de hacerlo sigue siendo incorrecta?
user225312
@AA: Agregué por qué el tuyo no funciona cuando quieres contar.
Jochen Ritzel
Ya veo, pero en mi caso los dos diccionarios tienen la misma longitud. Y siempre lo serán, porque así es como funciona el programa.
user225312
55
A partir de Python 3.6, dict se ordena fuera de la caja.
Phil
163
def dict_compare(d1, d2):
    d1_keys = set(d1.keys())
    d2_keys = set(d2.keys())
    shared_keys = d1_keys.intersection(d2_keys)
    added = d1_keys - d2_keys
    removed = d2_keys - d1_keys
    modified = {o : (d1[o], d2[o]) for o in shared_keys if d1[o] != d2[o]}
    same = set(o for o in shared_keys if d1[o] == d2[o])
    return added, removed, modified, same

x = dict(a=1, b=2)
y = dict(a=2, b=2)
added, removed, modified, same = dict_compare(x, y)
Daniel Myers
fuente
77
¡Este realmente maneja valores mutables en el dict!
Tim Tisdall
1
Cuando ejecuto esto, sigo recibiendo un error al tratar con los valores mutables: ValueError: el valor de verdad de un DataFrame es ambiguo. Use a.empty, a.bool (), a.item (), a.any () o a.all ().
Afflatus
2
@Afflatus - DataFrames por diseño no permiten comparaciones verdaderas (a menos que tenga una longitud de 1) ya que heredan de numpy.ndarray. -crédito para stackoverflow.com/a/33307396/994076
Daniel Myers
Esta es una joya absoluta.
pfabri
125

dic1 == dic2

De documentos de Python :

Para ilustrar, los siguientes ejemplos todos devuelven un diccionario igual a {"one": 1, "two": 2, "three": 3}:

>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> a == b == c == d == e
True

Proporcionar argumentos de palabras clave como en el primer ejemplo solo funciona para claves que son identificadores válidos de Python. De lo contrario, se puede usar cualquier clave válida.

Válido para ambos py2y py3.

CONvid19
fuente
3
No estoy de acuerdo con @ ErkinAlpGüney. ¿Podría proporcionar una prueba?
Qi Luo
44
No estoy de acuerdo con @ ErkinAlpGüney. La documentación oficial muestra que == de hecho compara los diccionarios por valor, no por dirección. docs.python.org/2/library/stdtypes.html#mapping-types-dict
Matthew Nakayama
3
Works for Python 2.7.13
Jesuisme
44
@ankostis:OrderedDict != dict
CONvid19
3
¿Puede proporcionar una entrada donde esto no es cierto?
CONvid19
55

Soy nuevo en Python pero terminé haciendo algo similar a @mouad

unmatched_item = set(dict_1.items()) ^ set(dict_2.items())
len(unmatched_item) # should be 0

El operador XOR ( ^) debe eliminar todos los elementos del dict cuando son iguales en ambos dictados.

philipp
fuente
28
Desafortunadamente, esto no funciona si los valores en el dict son mutables (es decir, no hashaable). (Ex {'a':{'b':1}}da TypeError: unhashable type: 'dict')
Tim Tisdall
54

Como parece que nadie mencionó deepdiff, lo agregaré aquí para completar. Me resulta muy conveniente para obtener diff de objetos (anidados) en general:

Instalación

pip install deepdiff

Código de muestra

import deepdiff
import json

dict_1 = {
    "a": 1,
    "nested": {
        "b": 1,
    }
}

dict_2 = {
    "a": 2,
    "nested": {
        "b": 2,
    }
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(diff, indent=4))

Salida

{
    "values_changed": {
        "root['a']": {
            "new_value": 2,
            "old_value": 1
        },
        "root['nested']['b']": {
            "new_value": 2,
            "old_value": 1
        }
    }
}

Nota sobre la impresión bonita del resultado para la inspección: el código anterior funciona si ambos dictos tienen las mismas claves de atributo (posiblemente con valores de atributo diferentes como en el ejemplo). Sin embargo, si un "extra"atributo está presente es uno de los dictados, json.dumps()falla con

TypeError: Object of type PrettyOrderedSet is not JSON serializable

Solución: use diff.to_json()y json.loads()/ json.dumps()para imprimir bonito:

import deepdiff
import json

dict_1 = {
    "a": 1,
    "nested": {
        "b": 1,
    },
    "extra": 3
}

dict_2 = {
    "a": 2,
    "nested": {
        "b": 2,
    }
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(json.loads(diff.to_json()), indent=4))  

Salida:

{
    "dictionary_item_removed": [
        "root['extra']"
    ],
    "values_changed": {
        "root['a']": {
            "new_value": 2,
            "old_value": 1
        },
        "root['nested']['b']": {
            "new_value": 2,
            "old_value": 1
        }
    }
}

Alternativa: uso pprint, resultados en un formato diferente:

import pprint

# same code as above

pprint.pprint(diff, indent=4)

Salida:

{   'dictionary_item_removed': [root['extra']],
    'values_changed': {   "root['a']": {   'new_value': 2,
                                           'old_value': 1},
                          "root['nested']['b']": {   'new_value': 2,
                                                     'old_value': 1}}}
Sumudu
fuente
2
Interesante. Gracias por responder esto. Útil para mí al menos. Esta respuesta necesita más votos a favor.
Archit Kapoor
46

Solo usa:

assert cmp(dict1, dict2) == 0
Shiyu
fuente
66
Parece que la tarea no es solo verificar si el contenido de ambos es el mismo, sino también dar un informe de las diferencias
Diego Tercero
29
Creo que esto es idéntico adict1 == dict2
Trey Hunner
10
Para cualquiera que use Python3.5, el cmpincorporado se ha eliminado (y debe tratarse como eliminado antes . Una alternativa que proponen: (a > b) - (a < b) == cmp(a, b)para un equivalente funcional (o mejor __eq__y __hash__)
nerdwaller
3
@nerdwaller: los dictados no son tipos ordenados, por lo que dict_a> dict_b generaría un TypeError:unorderable types: dict() < dict()
Stefano
2
@Stefano: Buena decisión, mi comentario fue más para una comparación general en Python (no estaba prestando atención a la respuesta real, mi error).
nerdwaller
9

La respuesta de @mouad es agradable si asume que ambos diccionarios contienen solo valores simples. Sin embargo, si tiene diccionarios que contienen diccionarios, obtendrá una excepción, ya que los diccionarios no se pueden compartir.

Fuera de mi cabeza, algo como esto podría funcionar:

def compare_dictionaries(dict1, dict2):
     if dict1 is None or dict2 is None:
        print('Nones')
        return False

     if (not isinstance(dict1, dict)) or (not isinstance(dict2, dict)):
        print('Not dict')
        return False

     shared_keys = set(dict1.keys()) & set(dict2.keys())

     if not ( len(shared_keys) == len(dict1.keys()) and len(shared_keys) == len(dict2.keys())):
        print('Not all keys are shared')
        return False


     dicts_are_equal = True
     for key in dict1.keys():
         if isinstance(dict1[key], dict) or isinstance(dict2[key], dict):
             dicts_are_equal = dicts_are_equal and compare_dictionaries(dict1[key], dict2[key])
         else:
             dicts_are_equal = dicts_are_equal and all(atleast_1d(dict1[key] == dict2[key]))

     return dicts_are_equal
Alejandro
fuente
Si utiliza en not isinstance(dict1, dict)lugar de type(dict1) is not dict, esto funcionará en otras clases basadas en dict. Also, instead of (dict1 [clave] == dict2 [clave]) , you can do all (atleast_1d (dict1 [clave] == dict2 [clave])) `para manejar matrices al menos.
EL_DON
+1, pero podrías salir de ti for looptan pronto como se dicts_are_equalvuelva falso. No hay necesidad de continuar más.
pfabri
6

Otra posibilidad más, hasta la última nota del OP, es comparar los hashes ( SHAo MD) de los dictados descargados como JSON. La forma en que se construyen los hashes garantiza que si son iguales, las cadenas de origen también lo son. Esto es muy rápido y matemáticamente sólido.

import json
import hashlib

def hash_dict(d):
    return hashlib.sha1(json.dumps(d, sort_keys=True)).hexdigest()

x = dict(a=1, b=2)
y = dict(a=2, b=2)
z = dict(a=1, b=2)

print(hash_dict(x) == hash_dict(y))
print(hash_dict(x) == hash_dict(z))
WoJ
fuente
2
Eso es completamente incorrecto, solo analizar los datos en json es realmente lento. Luego, cortar ese enorme corte que acabas de crear es aún peor. Nunca deberías hacer eso
Bruno
77
@Bruno: citando el OP: "Mejor no en velocidad, estoy hablando de la elegancia del código"
WoJ
2
No es elegante en absoluto, se siente inseguro y es demasiado complicado para un problema realmente simple
Bruno
77
@Bruno: la elegancia es subjetiva. Puedo entender que no te gusta (y probablemente desestimado). Esto no es lo mismo que "incorrecto".
WoJ
44
Esta es una respuesta genial. json.dumps(d, sort_keys=True)le dará JSON canónico para que pueda estar seguro de que ambos dict son equivalentes. También depende de lo que intentes lograr. Tan pronto como el valor no sea JSON serizalizable, fallará. Para quienes dicen que es ineficiente, echen un vistazo al proyecto ujson.
Natim
6

La función está bien IMO, clara e intuitiva. Pero solo para darle (otra) respuesta, aquí está mi ir:

def compare_dict(dict1, dict2):
    for x1 in dict1.keys():
        z = dict1.get(x1) == dict2.get(x1)
        if not z:
            print('key', x1)
            print('value A', dict1.get(x1), '\nvalue B', dict2.get(x1))
            print('-----\n')

Puede ser útil para usted o para cualquier otra persona.

EDITAR:

He creado una versión recursiva de la anterior. No he visto eso en las otras respuestas.

def compare_dict(a, b):
    # Compared two dictionaries..
    # Posts things that are not equal..
    res_compare = []
    for k in set(list(a.keys()) + list(b.keys())):
        if isinstance(a[k], dict):
            z0 = compare_dict(a[k], b[k])
        else:
            z0 = a[k] == b[k]

        z0_bool = np.all(z0)
        res_compare.append(z0_bool)
        if not z0_bool:
            print(k, a[k], b[k])
    return np.all(res_compare)
zwep
fuente
2
Vamos a mejorarlo para que funcione en ambos sentidos. Línea 2: "para x1 en el conjunto (dict1.keys ()). Union (dict2.keys ()):"
nkadwa
Gracias @nkadwa, lo hace ahora
zwep
5

Para probar si dos dictos son iguales en claves y valores:

def dicts_equal(d1,d2):
    """ return True if all keys and values are the same """
    return all(k in d2 and d1[k] == d2[k]
               for k in d1) \
        and all(k in d1 and d1[k] == d2[k]
               for k in d2)

Si desea devolver los valores que difieren, escríbalo de manera diferente:

def dict1_minus_d2(d1, d2):
    """ return the subset of d1 where the keys don't exist in d2 or
        the values in d2 are different, as a dict """
    return {k,v for k,v in d1.items() if k in d2 and v == d2[k]}

Tendrías que llamarlo dos veces, es decir

dict1_minus_d2(d1,d2).extend(dict1_minus_d2(d2,d1))
simonltwick
fuente
3

Código

def equal(a, b):
    type_a = type(a)
    type_b = type(b)
    
    if type_a != type_b:
        return False
    
    if isinstance(a, dict):
        if len(a) != len(b):
            return False
        for key in a:
            if key not in b:
                return False
            if not equal(a[key], b[key]):
                return False
        return True

    elif isinstance(a, list):
        if len(a) != len(b):
            return False
        while len(a):
            x = a.pop()
            index = indexof(x, b)
            if index == -1:
                return False
            del b[index]
        return True
        
    else:
        return a == b

def indexof(x, a):
    for i in range(len(a)):
        if equal(x, a[i]):
            return i
    return -1

Prueba

>>> a = {
    'number': 1,
    'list': ['one', 'two']
}
>>> b = {
    'list': ['two', 'one'],
    'number': 1
}
>>> equal(a, b)
True
Yas
fuente
3

Una simple comparación con == debería ser suficiente hoy en día (python 3.8). Incluso cuando compara los mismos dictados en un orden diferente (último ejemplo). Lo mejor es que no necesita un paquete de terceros para lograr esto.

a = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
b = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}

c = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
d = {'one': 'dog', 'two': 'cat', 'three': 'mouse', 'four': 'fish'}

e = {'one': 'cat', 'two': 'dog', 'three': 'mouse'}
f = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}

g = {'two': 'cat', 'one': 'dog', 'three': 'mouse'}
h = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}


print(a == b) # True
print(c == d) # False
print(e == f) # False
print(g == h) # True
Nebulosa
fuente
2

¡Llegar tarde en mi respuesta es mejor que nunca!

Compare Not_Equal es más eficiente que comparar Equal. Como tales dos dictos no son iguales si alguno de los valores clave en un dict no se encuentra en el otro dict. El siguiente código tiene en cuenta que tal vez esté comparando dict por defecto y por lo tanto usa get en lugar de getitem [].

Usar un tipo de valor aleatorio como predeterminado en la llamada get igual a la clave que se está recuperando, en caso de que los dictados tengan un valor None como valor en un dict y esa clave no exista en el otro. Además, la condición get! = Se verifica antes de que no esté en condiciones de eficiencia porque está haciendo la verificación de las claves y los valores de ambos lados al mismo tiempo.

def Dicts_Not_Equal(first,second):
    """ return True if both do not have same length or if any keys and values are not the same """
    if len(first) == len(second): 
        for k in first:
            if first.get(k) != second.get(k,k) or k not in second: return (True)
        for k in second:         
            if first.get(k,k) != second.get(k) or k not in first: return (True)
        return (False)   
    return (True)
usuario-asterix
fuente
2

Estoy usando esta solución que funciona perfectamente para mí en Python 3


import logging
log = logging.getLogger(__name__)

...

    def deep_compare(self,left, right, level=0):
        if type(left) != type(right):
            log.info("Exit 1 - Different types")
            return False

        elif type(left) is dict:
            # Dict comparison
            for key in left:
                if key not in right:
                    log.info("Exit 2 - missing {} in right".format(key))
                    return False
                else:
                    if not deep_compare(left[str(key)], right[str(key)], level +1 ):
                        log.info("Exit 3 - different children")
                        return False
            return True
        elif type(left) is list:
            # List comparison
            for key in left:
                if key not in right:
                    log.info("Exit 4 - missing {} in right".format(key))
                    return False
                else:
                    if not deep_compare(left[left.index(key)], right[right.index(key)], level +1 ):
                        log.info("Exit 5 - different children")
                        return False
            return True
        else:
            # Other comparison
            return left == right

        return False

Compara dict, list y cualquier otro tipo que implemente el operador "==" por sí mismo. Si necesita comparar algo diferente, debe agregar una nueva rama en el "árbol de if".

Espero que ayude.

Giovanni Basolu
fuente
2

para python3:

data_set_a = dict_a.items()
data_set_b = dict_b.items()

difference_set = data_set_a ^ data_set_b
Bryant
fuente
1
>>> hash_1
{'a': 'foo', 'b': 'bar'}
>>> hash_2
{'a': 'foo', 'b': 'bar'}
>>> set_1 = set (hash_1.iteritems())
>>> set_1
set([('a', 'foo'), ('b', 'bar')])
>>> set_2 = set (hash_2.iteritems())
>>> set_2
set([('a', 'foo'), ('b', 'bar')])
>>> len (set_1.difference(set_2))
0
>>> if (len(set_1.difference(set_2)) | len(set_2.difference(set_1))) == False:
...    print "The two hashes match."
...
The two hashes match.
>>> hash_2['c'] = 'baz'
>>> hash_2
{'a': 'foo', 'c': 'baz', 'b': 'bar'}
>>> if (len(set_1.difference(set_2)) | len(set_2.difference(set_1))) == False:
...     print "The two hashes match."
...
>>>
>>> hash_2.pop('c')
'baz'

Aquí hay otra opción:

>>> id(hash_1)
140640738806240
>>> id(hash_2)
140640738994848

Entonces, como ves, las dos identificaciones son diferentes. Pero los operadores de comparación ricos parecen hacer el truco:

>>> hash_1 == hash_2
True
>>>
>>> hash_2
{'a': 'foo', 'b': 'bar'}
>>> set_2 = set (hash_2.iteritems())
>>> if (len(set_1.difference(set_2)) | len(set_2.difference(set_1))) == False:
...     print "The two hashes match."
...
The two hashes match.
>>>
Led Zeppelin
fuente
1

En PyUnit hay un método que compara los diccionarios maravillosamente. Lo probé usando los siguientes dos diccionarios, y hace exactamente lo que estás buscando.

d1 = {1: "value1",
      2: [{"subKey1":"subValue1",
           "subKey2":"subValue2"}]}
d2 = {1: "value1",
      2: [{"subKey2":"subValue2",
           "subKey1": "subValue1"}]
      }


def assertDictEqual(self, d1, d2, msg=None):
        self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
        self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')

        if d1 != d2:
            standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
            diff = ('\n' + '\n'.join(difflib.ndiff(
                           pprint.pformat(d1).splitlines(),
                           pprint.pformat(d2).splitlines())))
            standardMsg = self._truncateMessage(standardMsg, diff)
            self.fail(self._formatMessage(msg, standardMsg))

No recomiendo importar unittesta su código de producción. Mi pensamiento es que la fuente en PyUnit podría modificarse para ejecutarse en producción. Utiliza pprintqué "impresiones bonitas" los diccionarios. Parece bastante fácil adaptar este código para que esté "listo para la producción".

MikeyE
fuente
1

ver objetos de vista de diccionario: https://docs.python.org/2/library/stdtypes.html#dict

De esta forma, puede restar dictView2 de dictView1 y devolverá un conjunto de pares clave / valor que son diferentes en dictView2:

original = {'one':1,'two':2,'ACTION':'ADD'}
originalView=original.viewitems()
updatedDict = {'one':1,'two':2,'ACTION':'REPLACE'}
updatedDictView=updatedDict.viewitems()
delta=original | updatedDict
print delta
>>set([('ACTION', 'REPLACE')])

Puede intersectar, unir, diferenciar (se muestra arriba), diferencia simétrica de estos objetos de vista de diccionario.
¿Mejor? ¿Más rápido? - no estoy seguro, pero es parte de la biblioteca estándar, lo que lo convierte en una gran ventaja para la portabilidad

tranimatronic
fuente
1

El siguiente código lo ayudará a comparar la lista de dict en python

def compate_generic_types(object1, object2):
    if isinstance(object1, str) and isinstance(object2, str):
        return object1 == object2
    elif isinstance(object1, unicode) and isinstance(object2, unicode):
        return object1 == object2
    elif isinstance(object1, bool) and isinstance(object2, bool):
        return object1 == object2
    elif isinstance(object1, int) and isinstance(object2, int):
        return object1 == object2
    elif isinstance(object1, float) and isinstance(object2, float):
        return object1 == object2
    elif isinstance(object1, float) and isinstance(object2, int):
        return object1 == float(object2)
    elif isinstance(object1, int) and isinstance(object2, float):
        return float(object1) == object2

    return True

def deep_list_compare(object1, object2):
    retval = True
    count = len(object1)
    object1 = sorted(object1)
    object2 = sorted(object2)
    for x in range(count):
        if isinstance(object1[x], dict) and isinstance(object2[x], dict):
            retval = deep_dict_compare(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False
        elif isinstance(object1[x], list) and isinstance(object2[x], list):
            retval = deep_list_compare(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False
        else:
            retval = compate_generic_types(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False

    return retval

def deep_dict_compare(object1, object2):
    retval = True

    if len(object1) != len(object2):
        return False

    for k in object1.iterkeys():
        obj1 = object1[k]
        obj2 = object2[k]
        if isinstance(obj1, list) and isinstance(obj2, list):
            retval = deep_list_compare(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False

        elif isinstance(obj1, dict) and isinstance(obj2, dict):
            retval = deep_dict_compare(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False
        else:
            retval = compate_generic_types(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False

    return retval
Vitthal Kadam
fuente
3
¡Bienvenido a Stack Overflow! Si bien este fragmento de código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no saber los motivos de su sugerencia de código. ¡Intente también no saturar su código con comentarios explicativos, esto reduce la legibilidad tanto del código como de las explicaciones!
Filnor
1
>>> x = {'a':1,'b':2,'c':3}
>>> x
{'a': 1, 'b': 2, 'c': 3}

>>> y = {'a':2,'b':4,'c':3}
>>> y
{'a': 2, 'b': 4, 'c': 3}

METHOD 1:

>>> common_item = x.items()&y.items() #using union,x.item() 
>>> common_item
{('c', 3)}

METHOD 2:

 >>> for i in x.items():
        if i in y.items():
           print('true')
        else:
           print('false')


false
false
true
vidiv
fuente
0

En Python 3.6, se puede hacer como: -

if (len(dict_1)==len(dict_2): 
  for i in dict_1.items():
        ret=bool(i in dict_2.items())

La variable ret será verdadera si todos los elementos de dict_1 están presentes en dict_2

Souravi Sinha
fuente
0

Aquí está mi respuesta, use una forma recursiva:

def dict_equals(da, db):
    if not isinstance(da, dict) or not isinstance(db, dict):
        return False
    if len(da) != len(db):
        return False
    for da_key in da:
        if da_key not in db:
            return False
        if not isinstance(db[da_key], type(da[da_key])):
            return False
        if isinstance(da[da_key], dict):
            res = dict_equals(da[da_key], db[da_key])
            if res is False:
                return False
        elif da[da_key] != db[da_key]:
            return False
    return True

a = {1:{2:3, 'name': 'cc', "dd": {3:4, 21:"nm"}}}
b = {1:{2:3, 'name': 'cc', "dd": {3:4, 21:"nm"}}}
print dict_equals(a, b)

¡Espero que ayude!

William Xu
fuente
0

¿Por qué no simplemente recorrer un diccionario y verificar el otro en el proceso (suponiendo que ambos diccionarios tengan las mismas claves)?

x = dict(a=1, b=2)
y = dict(a=2, b=2)

for key, val in x.items():
    if val == y[key]:
        print ('Ok', val, y[key])
    else:
        print ('Not', val, y[key])

Salida:

Not 1 2
Ok 2 2
LevB
fuente
0

La forma más fácil (y una de las más sólidas) de hacer una comparación profunda de dos diccionarios es serializarlos en formato JSON, ordenar las claves y comparar los resultados de la cadena:

import json
if json.dumps(x, sort_keys=True) == json.dumps(y, sort_keys=True):
   ... Do something ...
Krasimir Kalinov Kostadinov
fuente
-7
import json

if json.dumps(dict1) == json.dumps(dict2):
    print("Equal")
Mariusz K
fuente
1
Es posible que esto no haga lo que se solicitó exactamente, y extrae json std lib, pero funciona (como json.dumpses determinista con la configuración predeterminada).
Daniel Farrell el