Trouver la clé de valeur dans le dictionnaire Python:

assez nouveau en Python, toujours aux prises avec tant d'informations.

toute la documentation que j'ai vu sur les dictionnaires explique différentes façons d'obtenir une valeur via une clé - mais je cherche une façon pythonique de faire le contraire - obtenir une clé via une valeur.

je sais que je peux faire une boucle à travers les touches et inspecter leurs valeurs jusqu'à ce que je trouve la valeur que je cherche et puis attraper la clé, mais je suis à la recherche d'une route directe.

12
demandé sur Vector 2011-10-05 10:27:03

4 réponses

il n'y a pas de route directe. C'est assez facile avec les compréhensions de liste, cependant;

[k for k, v in d.iteritems() if v == desired_value]

si vous avez besoin de faire ceci de temps en temps et ne pensez pas que cela vaut la peine tout en l'indexant de l'autre manière aussi bien, vous pourriez faire quelque chose comme:

class bidict(dict):
    def key_with_value(self, value, default=None):
        for k, v in self.iteritems():
            if v == value:
                return v
        return default

    def keys_with_value(self, value, default=None):
        return [v for k, v in self.iteritems() if v == value]

puis d.key_with_value se comporterait plutôt comme d.get , sauf l'inverse.

vous pouvez également faire une classe qui indexé dans les deux sens automatiquement. La clé et la valeur devraient toutes deux être hachables, alors. Voici trois façons dont il pourrait être mis en œuvre:

  • en deux dicts séparés, avec l'exposition de certaines méthodes de type dict; vous pourriez peut-être faire foo.by_key[key] ou foo.by_value[value] . (Aucun code donné car c'est plus compliqué et je suis paresseux et je pense que c'est sous-optimal de toute façon.)

  • dans une structure différente, de sorte que vous pouvez faire d[key] et d.inverse[value] :

    class bidict(dict):
        def __init__(self, *args, **kwargs):
            self.inverse = {}
            super(bidict, self).__init__(key, value)
    
        def __setitem__(self, key, value):
            super(bidict, self).__setitem__(key, value)
            self.inverse[value] = key
    
        def __delitem__(self, key):
            del self.inverse[self[key]]
            super(bidict, self).__delitem__(key)
    
  • dans la même structure, pour que vous puissiez faire d[key] et d[value] :

    class bidict(dict):
        def __setitem__(self, key, value):
            super(bidict, self).__setitem__(key, value)
            super(bidict, self).__setitem__(value, key)
    
        def __delitem__(self, key):
            super(bidict, self).__delitem__(self[key])
            super(bidict, self).__delitem__(key)
    

(absent notamment de ces implémentations d'une bidict est la méthode update qui sera un peu plus complexe (mais help(dict.update) indiquera ce que vous devez couvrir). Sans update , bidict({1:2}) ne ferait pas ce à quoi il était destiné, ni ne ferait d.update({1:2}) .)

examiner également si une autre structure de données serait plus appropriée.

26
répondu Chris Morgan 2011-10-05 06:56:18

puisque votre dictionnaire peut contenir des valeurs dupliquées (c.-à-d. {'a': 'A', 'b': 'A'} ), la seule façon de trouver une clé à partir de la valeur est d'itérer sur le dictionnaire comme vous le décrivez.

Or... construisez le dictionnaire opposé. vous devez le recréer après chaque modification du dictionnaire original.

Or... Ecrivez un cours qui maintient le dictionnaire dans les deux sens. Vous devrez gérer les situations où la valeur dupliquée apparaît.

6
répondu eumiro 2011-10-05 06:29:45

la première solution avec la compréhension de liste est bonne. mais une petite correction pour python 3.x, au lieu de .iteritems() il devrait être juste .items() :

[k for k, v in d.items() if v == desired_value]
1
répondu Idan Richman 2017-12-05 14:37:14

construire un dictionnaire opposé n'est pas du tout de bonne manière car une ou plusieurs clés ont la même valeur, mais si vous l'inversez, vous devez insérer la clé:[value1,... ] la structure qui vous mènera à un autre problème.

0
répondu Raj Damani 2016-03-07 06:30:32