Supposons que j'ai deux dictionnaires Python - dictA
et dictB
. J'ai besoin de savoir s'il y a des clés qui sont présentes dictB
mais pas dedans dictA
. Quelle est la manière la plus rapide d'y parvenir?
Dois-je convertir les clés du dictionnaire en un ensemble, puis continuer?
Intéressé à connaître vos pensées ...
Merci pour vos réponses.
Toutes mes excuses pour ne pas avoir posé correctement ma question. Mon scénario est le suivant - j'ai un dictA
qui peut être le même que dictB
ou peut avoir des clés manquantes par rapport à dictB
ou bien la valeur de certaines clés peut être différente et doit être définie sur celle de dictA
la valeur de la clé.
Le problème est que le dictionnaire n'a pas de norme et peut avoir des valeurs qui peuvent être dictées par dict.
Dire
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 'key2' doit être réinitialisée à la nouvelle valeur et 'key13' doit être ajoutée à l'intérieur du dict. La valeur de clé n'a pas de format fixe. Il peut s'agir d'une simple valeur ou d'un dict ou d'un dict de dict.
la source
def update(self, new_dict): self.__init__(new_dict, self.current_dict)
ou autre pour pouvoir faire une comparaison glissanteDictDiffer
classe est une classe sans état et pourrait être une fonction. Les valeurschanged
etunchanged
peuvent être calculées dans la même boucle. Ces deux fonctions pourraient renvoyer alist
au lieu de aset
ce qui est certainement moins cher. Pour une comparaison approfondie, vous pouvez jeter un œil au framework de test unitaire: docs.python.org/2/library/unittest.html , suivez simplement laassertDictEqual
méthode dans le code source.set(dictb)
est probablement mieux queset(dictb.keys())
.Au cas où vous voudriez la différence récursivement, j'ai écrit un paquet pour python: https://github.com/seperman/deepdiff
Installation
Installer depuis PyPi:
Exemple d'utilisation
Importation
Le même objet retourne vide
Le type d'article a changé
La valeur d'un article a changé
Article ajouté et / ou supprimé
Différence de cordes
Différence de cordes 2
Changement de type
Différence de liste
Différence de liste 2:
Différence de liste en ignorant l'ordre ou les doublons: (avec les mêmes dictionnaires que ci-dessus)
Liste contenant le dictionnaire:
Ensembles:
Tuples nommés:
Objets personnalisés:
Attribut d'objet ajouté:
la source
ignore_order=True
. Vous pouvez trouver la documentation sur deepdiff.readthedocs.io/en/latest/diff.htmlje ne sais pas si c'est "rapide" ou pas, mais normalement, on peut le faire
la source
dicta
etdictb
puisqu'il veut savoir que ces clésdictb
ne sont pas dedansdicta
.for key in dicta.keys():
=>for key in dicta:
Comme l'a écrit Alex Martelli, si vous voulez simplement vérifier si une clé de B n'est pas dans A, ce
any(True for k in dictB if k not in dictA)
serait la voie à suivre.Pour trouver les clés manquantes:
Donc, ces deux solutions sont à peu près la même vitesse.
la source
any(k not in dictA for k in dictB)
Si vous voulez vraiment dire exactement ce que vous dites (que vous avez seulement besoin de savoir SI "il y a des clés" en B et non en A, pas QUELLES peuvent-elles être le cas échéant), le moyen le plus rapide devrait être:
Si vous avez réellement besoin de savoir QUELLES CLÉS, le cas échéant, 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 en effet ce que tu veux dire ;-).
la source
Utilisez
set()
:la source
set(d)
renvoie déjà uniquement les clés, donc vous pouvez le faireset(da).intersection(db)
La meilleure réponse de Hughdbrown suggère d'utiliser la différence d'ensemble, ce qui est certainement la meilleure approche:
Le problème avec ce code est qu'il construit deux listes juste pour créer deux ensembles, il perd donc 4N de temps et 2N d'espace. C'est aussi un peu plus compliqué que nécessaire.
Habituellement, ce n'est pas un gros problème, mais si c'est le cas:
collections.abc.Mapping
a unKeysView
qui agit comme unSet
.Python 2
Dans Python 2,
keys()
renvoie une liste des clés, pas un fichierKeysView
. Il faut donc demanderviewkeys()
directement.Pour le code à double version 2.7 / 3.x, nous espérons que vous utilisez
six
ou quelque chose de similaire, vous pouvez donc utilisersix.viewkeys(dictb)
:En 2.4-2.6, il n'y a pas de
KeysView
. Mais vous pouvez au moins réduire le coût de 4N à N en construisant votre ensemble de gauche directement à partir d'un itérateur, au lieu de créer d'abord une liste:Articles
Vous n'avez donc pas vraiment besoin de comparer les clés, mais les éléments. An
ItemsView
n'est a queSet
si les valeurs sont hachables, comme les chaînes. S'ils le sont, c'est facile:Diff récursif
Bien que la question ne demande pas directement un diff récursif, certaines des valeurs d'exemple sont des dicts, et il semble que la sortie attendue les diffère récursivement. Il y a déjà plusieurs réponses ici montrant comment faire cela.
la source
Il y a une autre question dans stackoverflow à propos de cet argument et je dois admettre qu'il existe une solution simple expliquée: la bibliothèque datadiff de python permet d'imprimer la différence entre deux dictionnaires.
la source
Voici une méthode qui fonctionnera, permet aux clés qui évaluent à
False
, et utilise toujours une expression de générateur pour tomber tôt si possible. Ce n'est pas exceptionnellement joli cependant.ÉDITER:
THC4k a publié une réponse à mon commentaire sur une autre réponse. Voici une meilleure et plus jolie façon de faire ce qui précède:
Je ne sais pas comment cela ne m'a jamais traversé l'esprit ...
la source
any(k for k in dictB if k not in dictA)
ce qui n'est pas la même chose (pour les fausses clés). Vérifiez l'historique des modifications / les horodatages.C'est une vieille question et demande un peu moins que ce dont j'avais besoin, donc cette réponse résout en fait plus que cette question ne le demande. Les réponses à cette question m'ont aidé à résoudre les problèmes suivants:
Tout cela combiné avec JSON permet un support de stockage de configuration assez puissant.
La solution ( également sur github ):
la source
qu'en est-il de standart (comparer FULL Object)
PyDev-> nouveau module PyDev-> Module: unittest
la source
Si sur Python ≥ 2.7:
la source
Voici une solution pour comparer en profondeur 2 clés de dictionnaires:
la source
voici une solution qui permet de comparer plus de deux dictats:
exemple d'utilisation:
la source
Ma recette de différence symétrique entre deux dictionnaires:
Et le résultat est:
la source
Comme mentionné dans d'autres réponses, unittest produit une sortie intéressante pour comparer les dictionnaires, mais dans cet exemple, nous ne voulons pas avoir à construire un test complet en premier.
En grattant la source la plus simple, il semble que vous pouvez obtenir une solution équitable avec juste ceci:
alors
Résulte en:
Où:
Comme dans unittest, la seule mise en garde est que le mappage final peut être considéré comme un diff, en raison de la virgule / crochet de fin.
la source
@Maxx a une excellente réponse, utilisez les
unittest
outils fournis par Python:Ensuite, n'importe où dans votre code, vous pouvez appeler:
La sortie résultante ressemble à la sortie de
diff
, en imprimant joliment les dictionnaires avec+
ou en-
ajoutant chaque ligne qui est différente.la source
Je ne sais pas si c'est toujours pertinent mais je suis tombé sur ce problème, ma situation j'avais juste besoin de retourner un dictionnaire des changements pour tous les dictionnaires imbriqués, etc. Je n'ai pas pu trouver une bonne solution mais j'ai fini par écrire une fonction simple pour faire ça . J'espère que cela t'aides,
la source
Si vous voulez une solution intégrée pour une comparaison complète avec des structures dict arbitraires, la réponse de @ Maxx est un bon début.
la source
Basé sur la réponse de ghostdog74,
affichera une valeur différente de dicta
la source
Essayez ceci pour trouver l'intersection, les clés qui sont dans les deux dictionarie, si vous voulez que les clés ne se trouvent pas sur la deuxième dictionarie, utilisez simplement le not in ...
la source