Comparaison de deux dictionnaires et vérification du nombre de paires (clé, valeur) égales

246

J'ai deux dictionnaires, mais pour simplifier, je prendrai ces deux:

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

Maintenant, je veux comparer si chaque key, valuepaire xa la même valeur correspondante y. J'ai donc écrit ceci:

>>> 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

Et cela fonctionne car a tupleest retourné puis comparé pour l'égalité.

Mes questions:

Est-ce correct? Existe-t-il une meilleure façon de procéder? Mieux vaut pas en vitesse, je parle d'élégance du code.

MISE À JOUR: J'ai oublié de mentionner que je dois vérifier combien de key, valuepaires sont égales.

user225312
la source
21
x == ydevrait être vrai selon stackoverflow.com/a/5635309/186202
Natim
x == y devrait être vrai. On peut vérifier rapidement dans REPL. Veuillez vous référer: docs.python.org/2/library/stdtypes.html#mapping-types-dict
Vikrant

Réponses:

179

Si vous voulez savoir combien de valeurs correspondent dans les deux dictionnaires, vous auriez dû le dire :)

Peut-être quelque chose comme ça:

shared_items = {k: x[k] for k in x if k in y and x[k] == y[k]}
print len(shared_items)
mouad
la source
1
Même erreur s'il y a un élément de liste pour la touche dict. Je pense que cmp est la meilleure façon de le faire, sauf si je manque quelque chose.
Mutant
@Mutant, c'est un problème différent. Vous ne pouvez pas créer un dictionnaire avec une listclé en premier lieu. x = {[1,2]: 2}échouera. La question est déjà valable dicts.
AnnanFay
@annan: faux, la question est générique. l' exemple dans la description de la question a déjà "dict valides". Si je poste une nouvelle question, avec le même titre, mais avec un dict différent "invalide", quelqu'un la marquera comme doublon. Downvoting.
ribamar
6
@ribamar la question est "Comparer deux dictionnaires [...]". Le «dict invalide» ci-dessus avec des listclés n'est pas un code python valide - les clés du dict doivent être immuables. Par conséquent, vous ne comparez pas les dictionnaires. Si vous essayez d'utiliser une liste comme clé de dictionnaire, votre code ne s'exécutera pas. Vous n'avez aucun objet à comparer. C'est comme taper x = dict(23\;dfg&^*$^%$^$%^)puis se plaindre du fait que la comparaison ne fonctionne pas avec le dictionnaire. Bien sûr, cela ne fonctionnera pas. Le commentaire de Tim, d'autre part, concerne les mutables values, d'où la raison pour laquelle j'ai dit que ce sont des questions différentes.
AnnanFay
1
@MikeyE - setnécessite que les valeurs soient lavables et dictque les clés soient lavables. set(x.keys())fonctionnera toujours car les clés doivent être lavables, mais set(x.values())échouera sur les valeurs qui ne sont pas lavables.
Tim Tisdall
173

Ce que vous voulez faire, c'est simplement x==y

Ce que vous faites n'est pas une bonne idée, car les éléments d'un dictionnaire ne sont pas censés avoir d'ordre. Vous pourriez comparer [('a',1),('b',1)]avec [('b',1), ('a',1)](mêmes dictionnaires, ordre différent).

Par exemple, voyez ceci:

>>> 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 différence n'est qu'un élément, mais votre algorithme verra que tous les éléments sont différents

Jochen Ritzel
la source
@ THC4k, désolé de ne pas l'avoir mentionné. Mais je dois vérifier combien de valeurs correspondent dans les deux dictionnaires.
user225312
Ok, donc sur la base de ma mise à jour, ma façon de faire est-elle toujours incorrecte?
user225312
@AA: J'ai ajouté pourquoi le vôtre ne fonctionne pas quand vous voulez compter.
Jochen Ritzel
Je vois, mais dans mon cas, les deux dictionnaires sont de même longueur. Et ils le seront toujours, car c'est ainsi que fonctionne le programme.
user225312
5
À partir de Python 3.6, dict est prêt à l'emploi.
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
la source
7
Celui-ci gère en fait les valeurs mutables dans le dict!
Tim Tisdall
1
Lorsque j'exécute cela, j'obtiens toujours une erreur en voyant traiter les valeurs mutables: ValueError: La valeur de vérité d'un DataFrame est ambiguë. Utilisez a.empty, a.bool (), a.item (), a.any () ou a.all ().
Afflatus
2
@Afflatus- DataFrames par conception ne permet pas de comparaisons véridiques (sauf s'il a une longueur de 1) car ils héritent de numpy.ndarray. -credit à stackoverflow.com/a/33307396/994076
Daniel Myers
Ceci est un joyau absolu.
pfabri
125

dic1 == dic2

Depuis les documents python :

Pour illustrer, les exemples suivants renvoient tous un dictionnaire égal à {"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

La fourniture d'arguments de mots clés comme dans le premier exemple ne fonctionne que pour les clés qui sont des identificateurs Python valides. Sinon, toutes les clés valides peuvent être utilisées.

Valable pour py2et py3.

CONvid19
la source
3
Je ne suis pas d'accord avec @ ErkinAlpGüney. Pourriez-vous fournir une preuve?
Qi Luo
4
Je suis en désaccord avec @ ErkinAlpGüney. La documentation officielle montre que == compare en effet les dictionnaires par valeur et non par adresse. docs.python.org/2/library/stdtypes.html#mapping-types-dict
Matthew Nakayama
3
Fonctionne pour Python 2.7.13
Jesuisme
4
@ankostis:OrderedDict != dict
CONvid19
3
Pouvez-vous s'il vous plaît fournir une entrée où ce n'est pas vrai?
CONvid19
55

Je suis nouveau sur python mais j'ai fini par faire quelque chose de similaire à @mouad

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

L'opérateur XOR ( ^) doit éliminer tous les éléments du dict lorsqu'ils sont identiques dans les deux dict.

philipp
la source
28
Malheureusement, cela ne fonctionne pas si les valeurs du dict sont modifiables (c'est-à-dire non lavables). (Ex {'a':{'b':1}}donne TypeError: unhashable type: 'dict')
Tim Tisdall
54

Puisqu'il semble que personne n'a mentionné deepdiff , je vais l'ajouter ici pour être complet. Je trouve cela très pratique pour obtenir des objets différents (imbriqués) en général:

Installation

pip install deepdiff

Exemple de code

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

Production

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

Remarque sur l'impression du résultat pour inspection: le code ci-dessus fonctionne si les deux dict ont les mêmes clés d'attribut (avec éventuellement des valeurs d'attribut différentes comme dans l'exemple). Cependant, si un "extra"attribut est présent est l'un des dict, json.dumps()échoue avec

TypeError: Object of type PrettyOrderedSet is not JSON serializable

Solution: utilisez diff.to_json()et json.loads()/ json.dumps()pour joliment imprimer:

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

Production:

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

Alternative: utilisation pprint, entraîne une mise en forme différente:

import pprint

# same code as above

pprint.pprint(diff, indent=4)

Production:

{   '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
la source
2
Intéressant. Merci d'avoir répondu à cela. Utile pour moi au moins. Cette réponse a besoin de plus de votes positifs.
Archit Kapoor
46

Utilisez simplement:

assert cmp(dict1, dict2) == 0
Shiyu
la source
6
Il semble que la tâche ne consiste pas seulement à vérifier si le contenu des deux est le même mais aussi à rendre compte des différences
Diego Tercero
29
Je crois que c'est identique àdict1 == dict2
Trey Hunner
10
Pour tous ceux qui utilisent Python3.5, le module cmpintégré a été supprimé (et devrait être traité comme supprimé auparavant . Une alternative qu'ils proposent: (a > b) - (a < b) == cmp(a, b)pour un équivalent fonctionnel (ou mieux __eq__et __hash__)
nerdwaller
3
@nerdwaller - les pronostics ne sont pas des types pouvant être commandés, donc dict_a> dict_b soulèverait un TypeError:unorderable types: dict() < dict()
Stefano
2
@Stefano: Bon appel, mon commentaire était plus pour une comparaison générale en python (je ne faisais pas attention à la réponse réelle, mon erreur).
nerdwaller
9

La réponse de @mouad est intéressante si vous supposez que les deux dictionnaires contiennent uniquement des valeurs simples. Cependant, si vous avez des dictionnaires qui contiennent des dictionnaires, vous obtiendrez une exception car les dictionnaires ne sont pas hachables.

Du haut de ma tête, quelque chose comme ça pourrait fonctionner:

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
Alexandre
la source
Si vous utilisez à la not isinstance(dict1, dict)place de type(dict1) is not dict, cela fonctionnera sur d'autres classes basées sur dict. Also, instead of (dict1 [key] == dict2 [key]) , you can do all (atleast_1d (dict1 [key] == dict2 [key])) `pour gérer au moins les tableaux.
EL_DON
+1, mais vous pourriez sortir de votre for loopdès que votre dicts_are_equaldeviendrait faux. Il n'est pas nécessaire de continuer plus loin.
pfabri
6

Encore une autre possibilité, jusqu'à la dernière note de l'OP, est de comparer les hachages ( SHAou MD) des dicts sous JSON. La façon dont les hachages sont construits garantit que s'ils sont égaux, les chaînes source sont également égales. C'est très rapide et mathématiquement valable.

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
la source
2
C'est complètement faux, juste analyser les données dans json est vraiment lent. Le hachage de cette énorme chaîne que vous venez de créer est encore pire. Vous ne devriez jamais faire ça
Bruno
7
@Bruno: citant l'OP: "Mieux vaut pas en vitesse, je parle d'élégance du code"
WoJ
2
Ce n'est pas élégant du tout, cela ne semble pas sûr et c'est trop compliqué pour un problème vraiment simple
Bruno
7
@Bruno: l'élégance est subjective. Je peux comprendre que vous ne l'aimez pas (et probablement sous-estimé). Ce n'est pas la même chose que "faux".
WoJ
4
C'est une excellente réponse. json.dumps(d, sort_keys=True)vous donnera un JSON canonique afin que vous puissiez être certain que les deux dict sont équivalents. Cela dépend aussi de ce que vous essayez d'atteindre. Dès que la valeur n'est pas sérialisable JSON, elle échouera. Pour ceux qui disent qu'il est inefficace, jetez un œil au projet ujson.
Natim
6

La fonction est fine IMO, claire et intuitive. Mais juste pour vous donner une (autre) réponse, voici mon tour:

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')

Peut être utile pour vous ou pour quelqu'un d'autre ..

ÉDITER:

J'ai créé une version récursive de celle ci-dessus .. Je n'ai pas vu cela dans les autres réponses

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
la source
2
Améliorons-le pour qu'il fonctionne dans les deux sens. Ligne 2: "pour x1 dans l'ensemble (dict1.keys ()). Union (dict2.keys ()):"
nkadwa
Merci @nkadwa, il le fait maintenant
zwep
5

Pour tester si deux dict sont égaux en clés et en valeurs:

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 vous souhaitez renvoyer les valeurs qui diffèrent, écrivez-le différemment:

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]}

Il faudrait l'appeler deux fois, c'est-à-dire

dict1_minus_d2(d1,d2).extend(dict1_minus_d2(d2,d1))
simonltwick
la source
3

Code

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

Tester

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

Une simple comparaison avec == devrait suffire de nos jours (python 3.8). Même lorsque vous comparez les mêmes dictés dans un ordre différent (dernier exemple). La meilleure chose est que vous n'avez pas besoin d'un package tiers pour accomplir cela.

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
Nébulastique
la source
2

Être en retard dans ma réponse est mieux que jamais!

Comparer Not_Equal est plus efficace que comparer Equal. En tant que tels, deux dicts ne sont pas égaux si aucune valeur clé dans un dict n'est trouvée dans l'autre dict. Le code ci-dessous prend en compte que vous comparez peut-être dict par défaut et utilise donc get au lieu de getitem [].

Utiliser une sorte de valeur aléatoire par défaut dans l'appel get égale à la clé récupérée - juste au cas où les dicts ont une valeur None comme valeur dans un dict et que cette clé n'existe pas dans l'autre. De plus, la condition get! = Est vérifiée avant la condition non en état d'efficacité, car vous effectuez la vérification des clés et des valeurs des deux côtés en même temps.

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)
user-asterix
la source
2

J'utilise cette solution qui fonctionne parfaitement pour moi 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

Il compare dict, list et tout autre type qui implémente l'opérateur "==" par lui-même. Si vous avez besoin de comparer autre chose, vous devez ajouter une nouvelle branche dans l'arborescence "if".

J'espère que cela pourra aider.

Giovanni Basolu
la source
2

pour python3:

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

difference_set = data_set_a ^ data_set_b
Bryant
la source
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'

Voici une autre option:

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

Donc, comme vous le voyez, les deux identifiants sont différents. Mais les opérateurs de comparaison riches semblent faire l'affaire:

>>> 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
la source
1

Dans PyUnit, il existe une méthode qui compare magnifiquement les dictionnaires. Je l'ai testé en utilisant les deux dictionnaires suivants, et il fait exactement ce que vous recherchez.

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

Je ne recommande pas d'importer unittestdans votre code de production. Ma pensée est que la source dans PyUnit pourrait être ré-outillée pour fonctionner en production. Il utilise pprintqui "joliment imprime" les dictionnaires. Il semble assez facile d'adapter ce code pour qu'il soit "prêt pour la production".

MikeyE
la source
1

voir les objets de vue du dictionnaire: https://docs.python.org/2/library/stdtypes.html#dict

De cette façon, vous pouvez soustraire dictView2 de dictView1 et il retournera un ensemble de paires clé / valeur qui sont différentes dans 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')])

Vous pouvez intersecter, réunir, différencier (voir ci-dessus), différence symétrique ces objets de vue de dictionnaire.
Mieux? Plus rapide? - pas sûr, mais faisant partie de la bibliothèque standard - ce qui en fait un gros plus pour la portabilité

tranimatronic
la source
1

Le code ci-dessous vous aidera à comparer la liste des 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
la source
3
Bienvenue dans Stack Overflow! Bien que cet extrait de code puisse résoudre la question, y compris une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondrez à la question pour les lecteurs à l'avenir, et ces personnes pourraient ne pas connaître les raisons de votre suggestion de code. Essayez également de ne pas surcharger votre code avec des commentaires explicatifs, cela réduit la lisibilité du code et des explications!
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
la source
0

En Python 3.6, cela peut être fait comme: -

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

La variable ret sera vraie si tous les éléments de dict_1 sont présents dans dict_2

Souravi Sinha
la source
0

Voici ma réponse, utilisez une méthode récursive:

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)

J'espère que cela pourra aider!

William Xu
la source
0

Pourquoi ne pas simplement parcourir un dictionnaire et vérifier l'autre dans le processus (en supposant que les deux dictionnaires ont les mêmes clés)?

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])

Production:

Not 1 2
Ok 2 2
LevB
la source
0

La façon la plus simple (et l'une des plus robustes) de comparer en profondeur deux dictionnaires consiste à les sérialiser au format JSON, à trier les clés et à comparer les résultats de la chaîne:

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

if json.dumps(dict1) == json.dumps(dict2):
    print("Equal")
Mariusz K
la source
1
Cela peut ne pas faire exactement ce qui a été demandé et extrait la bibliothèque json std, mais cela fonctionne (comme json.dumpsc'est déterministe avec les paramètres par défaut).
Daniel Farrell