55 votes

Comparaison rapide entre deux dictionnaires Python

Supposons que j'ai deux dictionnaires Python - dictA y dictB . J'ai besoin de savoir s'il y a des clés qui sont présentes dans dictB mais pas dans dictA . Quel est le moyen le plus rapide d'y parvenir ?

Dois-je convertir les clés du dictionnaire en un ensemble et procéder ensuite ?

J'aimerais savoir ce que vous en pensez...


Merci pour vos réponses.

Je m'excuse de ne pas avoir formulé ma question correctement. Mon scénario est le suivant : j'ai un dictA qui peut être la même chose que dictB ou peut avoir quelques clés manquantes par rapport à dictB ou bien la valeur de certaines clés pourrait être différente, ce qui doit être mis à celle de dictA la valeur de la clé.

Le problème est que le dictionnaire n'a pas de norme et qu'il peut avoir des valeurs qui peuvent être le dict du dict.

Dites

dictA={'key1':a, 'key2':b, 'key3':{'key11':cc, 'key12':dd}, 'key4':{'key111':{....}}}
dictB={'key1':a, 'key2:':newb, 'key3':{'key11':cc, 'key12':newdd, 'key13':ee}.......

Ainsi, la valeur de 'key2' doit être réinitialisée à la nouvelle valeur et 'key13' doit être ajoutée dans le dict. La valeur de la clé n'a pas un format fixe. Il peut s'agir d'une simple valeur ou d'un dict ou d'un dict de dict.

104voto

hughdbrown Points 15770

Vous pouvez utiliser les opérations de réglage sur les touches :

diff = set(dictb.keys()) - set(dicta.keys())

Voici une classe permettant de trouver toutes les possibilités : ce qui a été ajouté, ce qui a été supprimé, quelles paires clé-valeur sont les mêmes, et quelles paires clé-valeur ont été modifiées.

class DictDiffer(object):
    """
    Calculate the difference between two dictionaries as:
    (1) items added
    (2) items removed
    (3) keys same in both but changed values
    (4) keys same in both and unchanged values
    """
    def __init__(self, current_dict, past_dict):
        self.current_dict, self.past_dict = current_dict, past_dict
        self.set_current, self.set_past = set(current_dict.keys()), set(past_dict.keys())
        self.intersect = self.set_current.intersection(self.set_past)
    def added(self):
        return self.set_current - self.intersect 
    def removed(self):
        return self.set_past - self.intersect 
    def changed(self):
        return set(o for o in self.intersect if self.past_dict[o] != self.current_dict[o])
    def unchanged(self):
        return set(o for o in self.intersect if self.past_dict[o] == self.current_dict[o])

Voici quelques exemples de résultats :

>>> a = {'a': 1, 'b': 1, 'c': 0}
>>> b = {'a': 1, 'b': 2, 'd': 0}
>>> d = DictDiffer(b, a)
>>> print "Added:", d.added()
Added: set(['d'])
>>> print "Removed:", d.removed()
Removed: set(['c'])
>>> print "Changed:", d.changed()
Changed: set(['b'])
>>> print "Unchanged:", d.unchanged()
Unchanged: set(['a'])

Disponible sous forme de repo github : https://github.com/hughdbrown/dictdiffer

12voto

Jochen Ritzel Points 42916

Comme l'a écrit Alex Martelli, si vous voulez simplement vérifier si une clé en B n'est pas en A, any(True for k in dictB if k not in dictA) serait la meilleure solution.

Pour trouver les clés qui manquent :

diff = set(dictB)-set(dictA) #sets

C:\Dokumente und Einstellungen\thc>python -m timeit -s "dictA =    
dict(zip(range(1000),range
(1000))); dictB = dict(zip(range(0,2000,2),range(1000)))" "diff=set(dictB)-set(dictA)"
10000 loops, best of 3: 107 usec per loop

diff = [ k for k in dictB if k not in dictA ] #lc

C:\Dokumente und Einstellungen\thc>python -m timeit -s "dictA = 
dict(zip(range(1000),range
(1000))); dictB = dict(zip(range(0,2000,2),range(1000)))" "diff=[ k for k in dictB if
k not in dictA ]"
10000 loops, best of 3: 95.9 usec per loop

Ces deux solutions ont donc à peu près la même vitesse.

10voto

ghostdog74 Points 86060

Je ne sais pas si c'est "rapide" ou non, mais normalement, on peut faire ça

dicta = {"a":1,"b":2,"c":3,"d":4}
dictb = {"a":1,"d":2}
for key in dicta.keys():
    if not key in dictb:
        print key

8voto

Alex Martelli Points 330805

Si vous pensez vraiment ce que vous dites (que vous avez seulement besoin de savoir SI "il y a des clés" en B et non en A, et non LESQUELLES, le cas échéant), la méthode la plus rapide devrait être la suivante :

if any(True for k in dictB if k not in dictA): ...

Si vous avez réellement besoin de savoir QUELLES CLÉS, s'il y en a, sont en B et non en A, et pas seulement "SI" il y a de telles clés, alors les réponses existantes sont tout à fait appropriées (mais je suggère plus de précision dans les questions futures si c'est bien ce que vous voulez dire;-).

3voto

softwareplay Points 307

Il y a un autre question dans stackoverflow sur cet argument et je dois admettre qu'il y a une solution simple expliquée : la bibliothèque datadiff de python permet d'imprimer la différence entre deux dictionnaires.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X