web-dev-qa-db-fra.com

Y a-t-il un meilleur moyen de comparer les valeurs du dictionnaire

J'utilise actuellement la fonction suivante pour comparer les valeurs du dictionnaire. Y a-t-il un moyen plus rapide ou meilleur de le faire?

match = True
for keys in dict1:
    if dict1[keys] != dict2[keys]:
        match = False
        print keys
        print dict1[keys],
        print  '->' ,
        print dict2[keys]

Edit: Les deux dits contiennent les mêmes clés.

36
randomThought

Si les dict ont des jeux de clés identiques et que vous avez besoin de toutes ces impressions pour toute différence de valeur, vous ne pouvez pas faire grand chose; peut-être quelque chose comme:

diffkeys = [k for k in dict1 if dict1[k] != dict2[k]]
for k in diffkeys:
  print k, ':', dict1[k], '->', dict2[k]

à peu près équivalent à ce que vous avez, mais vous pouvez obtenir une présentation plus agréable, par exemple, en triant les diffkeys avant de les afficher en boucle.

34
Alex Martelli

Si le but véritable de la question est la comparaison entre les dessins (plutôt que les différences d’impression), la réponse est:

dict1 == dict2

Cela a déjà été mentionné, mais j’ai senti que c’était un peu noyé dans d’autres informations. Cela peut paraître superficiel, mais la comparaison de valeur de dict a une sémantique puissante. Cela couvre

  • nombre de clés (si elles ne correspondent pas, les repères ne sont pas égaux)
  • noms des clés (si elles ne correspondent pas, elles ne sont pas égales)
  • valeur de chaque clé (elles doivent aussi être '==')

Le dernier point semble encore une fois trivial, mais il est réellement intéressant dans la mesure où il signifie que tout ceci s’applique récursivement aux dict imbriqués également. Par exemple.

 m1 = {'f':True}
 m2 = {'f':True}
 m3 = {'a':1, 2:2, 3:m1}
 m4 = {'a':1, 2:2, 3:m2}
 m3 == m4  # True

Des sémantiques similaires existent pour la comparaison de listes. Tout cela en fait une évidence, par exemple compare des structures Json profondes, seules avec un simple "==".

132
ThomasH

Vous pouvez utiliser des ensembles pour cela aussi

>>> a = {'x': 1, 'y': 2}
>>> b = {'y': 2, 'x': 1}
>>> set(a.iteritems())-set(b.iteritems())
set([])
>>> a['y']=3
>>> set(a.iteritems())-set(b.iteritems())
set([('y', 3)])
>>> set(b.iteritems())-set(a.iteritems())
set([('y', 2)])
>>> set(b.iteritems())^set(a.iteritems())
set([('y', 3), ('y', 2)])
9
John La Rooy

Uhm, vous décrivez dict1 == dict2 (vérifiez si les deux dict sont égaux)

Mais ce que fait votre code est all( dict1[k]==dict2[k] for k in dict1 ) (vérifiez si toutes les entrées de dict1 sont égales à celles de dict2)

7
Jochen Ritzel

Je ne suis pas sûr que cela aide, mais dans mon application, je devais vérifier si un dictionnaire avait changé.

Cela ne fonctionnera pas, car au fond c'est toujours le même objet:

val={'A':1,'B':2}
old_val=val

val['A']=10
if old_val != val:
  print('changed')

Utiliser copier/deepcopy fonctionne:

import copy
val={'A':1,'B':2}
old_val=copy.deepcopy(val)

val['A']=10
if old_val != val:
  print('changed')
2
erazor

Si vous comparez seulement pour l'égalité, vous pouvez simplement faire ceci:

if not dict1 == dict2:
    match = False

Sinon, le seul problème majeur que je vois est que vous obtiendrez une erreur KeyError s'il existe une clé dans dict1 qui n'est pas dans dict2. Vous souhaiterez peut-être faire quelque chose comme ceci:

for key in dict1:
    if not key in dict2 or dict1[key] != dict2[key]:
        match = False

Vous pouvez compresser ceci dans une compréhension pour obtenir simplement la liste des clés qui ne correspondent pas trop:

mismatch_keys = [key for key in x if not key in y or x[key] != y[key]]
match = not bool(mismatch_keys) #If the list is not empty, they don't match 
for key in mismatch_keys:
    print key
    print '%s -> %s' % (dict1[key],dict2[key])

La seule autre optimisation à laquelle je puisse penser serait d'utiliser "len (dict)" pour déterminer le dict ayant le moins d'entrées et de le parcourir en premier pour obtenir la boucle la plus courte possible.

1
Brent Writes Code
>>> a = {'x': 1, 'y': 2}
>>> b = {'y': 2, 'x': 1}
>>> print a == b
True
>>> c = {'z': 1}
>>> print a == c
False
>>> 
1
yedpodtrzitko

Si vos dictionnaires sont profondément imbriqués et s'ils contiennent différents types de collections, vous pouvez les convertir en chaîne json et les comparer.

import json
match = (json.dumps(dict1) == json.dumps(dict2))

attention, cette solution peut ne pas fonctionner si vos dictionnaires ont des chaînes binaires dans les valeurs, car cela n'est pas json sérialisable

0
user3283069