167 votes

Comment vérifier si un dictionnaire est un sous-ensemble d'un autre dictionnaire plus grand ?

J'essaye d'écrire une méthode de filtre personnalisée qui prend un nombre arbitraire de kwargs et renvoie une liste contenant les éléments d'une liste de type base de données qui contiennent les éléments suivants kwargs .

Par exemple, supposons que d1 = {'a':'2', 'b':'3'} y d2 = la même chose. d1 == d2 résulte en Vrai. Mais supposons que d2 = la même chose plus un tas d'autres choses. Ma méthode doit être capable de dire si d1 dans d2 mais Python ne peut pas faire cela avec les dictionnaires.

Le contexte :

J'ai une classe Word, et chaque objet a des propriétés telles que word , definition , part_of_speech et ainsi de suite. Je veux pouvoir appeler une méthode de filtrage sur la liste principale de ces mots, comme suit Word.objects.filter(word='jump', part_of_speech='verb-intransitive') . Je n'arrive pas à trouver comment gérer ces clés et ces valeurs en même temps. Mais cela pourrait avoir une fonctionnalité plus large en dehors de ce contexte pour d'autres personnes.

212voto

augurar Points 547

En Python 3, vous pouvez utiliser dict.items() pour obtenir une vue d'ensemble des éléments du dict. Vous pouvez ensuite utiliser la fonction <= pour vérifier si une vue est un "sous-ensemble" de l'autre :

d1.items() <= d2.items()

Dans Python 2.7, utilisez la fonction dict.viewitems() de faire de même :

d1.viewitems() <= d2.viewitems()

Dans Python 2.6 et inférieur, vous aurez besoin d'une solution différente, comme l'utilisation de all() :

all(key in d2 and d2[key] == d1[key] for key in d1)

145voto

Ignacio Vazquez-Abrams Points 312628

Convertir en paires d'éléments et vérifier le confinement.

all(item in superset.items() for item in subset.items())

L'optimisation est laissée comme un exercice pour le lecteur.

44voto

rednaw Points 3856

Remarque à l'intention des personnes qui en ont besoin pour les tests unitaires : il existe également une fonction assertDictContainsSubset() dans le langage Python TestCase classe.

http://docs.python.org/2/library/unittest.html?highlight=assertdictcontainssubset#unittest.TestCase.assertDictContainsSubset

Il est cependant déprécié dans la version 3.2, je ne sais pas trop pourquoi, il y a peut-être un remplaçant.

38voto

blubberdiblub Points 441

Pour être complet, vous pouvez également procéder ainsi :

def is_subdict(small, big):
    return dict(big, **small) == big

Cependant, je n'ai aucune prétention concernant la vitesse (ou le manque de vitesse) ou la lisibilité (ou le manque de lisibilité).

Mise à jour : comme l'a souligné Boris dans son commentaire, cette astuce ne fonctionne pas si votre petit dict a des clés qui ne sont pas des chaînes de caractères et si vous utilisez Python >= 3 (ou en d'autres termes : face à des clés tapées arbitrairement, cela ne fonctionne que dans l'ancien Python 2.x).

Si vous utilisez Python 3.9 ou plus récent Cependant, vous pouvez le faire fonctionner avec des touches non typées et obtenir une syntaxe encore plus soignée.

Si votre code a déjà les deux dictionnaires comme variables, il est très concis de vérifier cela en ligne :

if big | small == big:
    # do something

Sinon, ou si vous préférez une fonction réutilisable comme ci-dessus, vous pouvez utiliser ceci :

def is_subdict(small, big):
    return big | small == big

Le principe de fonctionnement est le même que celui de la première fonction, mais cette fois-ci en utilisant l'opérateur union qui a été étendu pour supporter les dicts.

26voto

kashchey Points 51

Pour l'utilisation des clés et des valeurs de contrôle : set(d1.items()).issubset(set(d2.items()))

si vous devez vérifier uniquement les clés : set(d1).issubset(set(d2))

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