Inverse de la recherche dans le dictionnaire en Python
Est-il un moyen simple de trouver une clé en connaissant la valeur dans un dictionnaire?
Tout ce que je peux penser, c'est ceci:
key = [key for key, value in dict_obj.items() if value == 'value'][0]
- double possible: stackoverflow.com/questions/483666/...
- jetez un oeil à ma réponse comment construire un dictionnaire inversé
- Google m'a guidé ici... Et je dois dire.. pourquoi pas une aide
iteritems
que pour moi cela fait une 40x plus rapide de différence... à l'aide de la ().méthode suivante - Si vous avez beaucoup de recherches inversées à faire:
reverse_dictionary = {v:k for k,v in dictionary.items()}
Vous devez vous connecter pour publier un commentaire.
Il n'y a aucun. N'oubliez pas que la valeur peut être trouvé sur un certain nombre de clés, y compris 0 ou supérieur à 1.
</sigh>
Votre liste de compréhension passe par tous les dict éléments de trouver tous les matchs, puis retourne juste la première clé. Ce générateur d'expression ne itérer autant que nécessaire pour revenir à la première valeur:
où
dd
est le dict. Va augmenterStopIteration
si aucune correspondance n'est trouvée, de sorte que vous pouvez attraper et retourner un plus approprié d'exception commeValueError
ouKeyError
.keys = { key for key,value in dd.items() if value=='value' }
pour obtenir l'ensemble de toutes les clés si plusieurs matchs.Il y a des cas où un dictionnaire est un:une cartographie
Par exemple,
Votre approche est ok si vous ne faites que d'une seule recherche. Toutefois, si vous avez besoin de faire plus d'une recherche, il sera plus efficace de créer un dictionnaire inverse
Si il y a une possibilité de plusieurs touches avec la même valeur, vous aurez besoin de spécifier le comportement souhaité dans ce cas.
Si votre Python 2.6 ou plus, vous pouvez utiliser
ivd=dict([(v,k) for (k,v) in d.items()])
invd = { v:k for k,v in d.items() }
Cette version est 26% plus courte que la vôtre mais fonctionne de manière identique, même pour redondante/valeurs ambiguës (renvoie le premier match, comme la vôtre n'). Cependant, il est probablement deux fois plus lent que le vôtre, car il crée une liste à partir du dict deux fois.
Ou si vous préférez la brièveté plus de lisibilité, vous pouvez enregistrer un caractère de plus avec
Et si vous préférez l'efficacité, @PaulMcGuire de approche est mieux. Si il y a beaucoup de touches qui partagent la même valeur, il est plus efficace de ne pas instancier la liste des clés de compréhension de liste et d'utiliser plutôt l'utilisation d'un générateur:
dict.keys()
etdict.values()
sont garantis correspondent aussi longtemps que ledict
n'est pas muté entre les appels.Peut-être un dictionnaire-comme la classe, comme
DoubleDict
en bas, est ce que vous voulez? Vous pouvez utiliser l'un quelconque des metaclasses en conjonction avecDoubleDict
ou peut éviter d'utiliser tout métaclasse à tous.Puisque c'est encore très pertinent, le premier Google a frappé et je viens de passer un peu de temps à essayer de comprendre cela, je vais poster mon (travail en Python 3) solution:
Il vous donnera la première valeur qui correspond à.
Il n'y a pas pour autant que je sache, d'une manière toutefois à faire est de créer un dict normal de la recherche par clé et un autre dict pour la recherche inversée par valeur.
Il y a un exemple d'une telle mise en œuvre ici:
http://code.activestate.com/recipes/415903-two-dict-classes-which-can-lookup-keys-by-value-an/
Cela signifie que la recherche les clés pour une valeur pourrait aboutir à plusieurs résultats qui peuvent être retournés comme une simple liste.
Non, vous ne pouvez pas le faire efficacement sans regarder à toutes les touches et de la vérification de toutes leurs valeurs. Vous aurez donc besoin de
O(n)
temps pour ce faire. Si vous avez besoin de faire beaucoup de ces recherches, vous aurez besoin pour ce faire de manière efficace par la construction d'un dictionnaire inversé (peut être fait aussi dansO(n)
) et ensuite faire une recherche à l'intérieur de ce dictionnaire inversé (chaque recherche prendra en moyenneO(1)
).Voici un exemple de la façon de construire un dictionnaire inversé (qui sera en mesure de le faire un à plusieurs mapping) à partir d'un dictionnaire:
Par exemple, si votre
votre
h_reversed
seraÀ travers des valeurs dans le dictionnaire peut être l'objet de quelque nature qu'ils ne peuvent pas être haché ou indexé autre manière. Afin de trouver la clé par la valeur n'est pas naturel pour ce type de collection. Toute requête qui peut être exécuté en O(n) fois seulement. Donc, si c'est fréquent tâche, vous devez prendre un coup d'oeil pour certains d'indexation de clé comme Jon sujjested ou peut-être même certains d'index spatial (DB ou http://pypi.python.org/pypi/Rtree/ ).
Je sais que cela peut être considéré comme "gaspillage", mais dans ce scénario, j'ai souvent stocker la clé comme une colonne supplémentaire dans la valeur record:
c'est un compromis et se sent mal, mais c'est simple et fonctionne et bien sûr, dépend des valeurs de n-uplets, plutôt que de simples valeurs.
Je suis en utilisant les dictionnaires comme une sorte de "base de données", j'ai donc besoin de trouver une clé que je peux réutiliser. Pour mon cas, si une valeur de clé est
None
, alors je peux le prendre et de le réutiliser sans avoir à "attribuer" un autre id. Juste pensé que je devais le partager.Je l'aime parce que je n'ai pas à essayer d'attraper les erreurs comme
StopIteration
ouIndexError
. Si il y a une clé disponible,free_id
contient une. Si il n'y en a pas, alors il sera simplementNone
. Probablement pas pythonic, mais je n'avais vraiment pas envie d'utiliser untry
ici...Que la valeur pourrait être inexistante dans les dict, plus pythonic et auto-documenté code serait:
En effet dicts ne sont pas faits pour répondre à ces problématiques, si vous rencontrez ce problème sur un nouveau programme conçu par, alors vous devriez sans doute revoir votre conception.
Créer un dictionnaire inverse. Ensuite, une recherche.
Exemple d'un livre de téléphone de recherche inversée:
C'est littéralement il