Finding key from value in Python dictionary:

前端 未结 4 2013
误落风尘
误落风尘 2020-12-06 10:53

Fairly new to Python, still struggling with so much information.

All the documentation I\'ve seen about dictionaries explain various ways of getting a value via a k

4条回答
  •  孤街浪徒
    2020-12-06 11:22

    There is no direct route. It's pretty easy with list comprehensions, though;

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

    If you need to do this occasionally and don't think it's worth while indexing it the other way as well, you could do something like:

    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]
    

    Then d.key_with_value would behave rather like d.get, except the other way round.

    You could also make a class which indexed it both ways automatically. Key and value would both need to be hashable, then. Here are three ways it could be implemented:

    • In two separate dicts, with the exposing some dict-like methods; you could perhaps do foo.by_key[key] or foo.by_value[value]. (No code given as it's more complicated and I'm lazy and I think this is suboptimal anyway.)

    • In a different structure, so that you could do d[key] and 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)
      
    • In the same structure, so that you could do d[key] and 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)
      

    (Notably absent from these implementations of a bidict is the update method which will be slightly more complex (but help(dict.update) will indicate what you'd need to cover). Without update, bidict({1:2}) wouldn't do what it was intended to, nor would d.update({1:2}).)

    Also consider whether some other data structure would be more appropriate.

提交回复
热议问题