Ответ 1
Прямого маршрута нет. Это довольно легко с учетом списка, однако;
[k for k, v in d.iteritems() if v == desired_value]
Если вам нужно сделать это время от времени и не думайте, что стоит его индексировать другим способом, вы можете сделать что-то вроде:
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]
Тогда d.key_with_value
будет вести себя скорее как d.get
, кроме наоборот.
Вы также можете создать класс, который автоматически индексировал его оба раза. Тогда ключ и значение должны были быть хешируемыми. Вот три способа его реализации:
-
В двух отдельных dicts с разоблачением некоторых диктоподобных методов; вы могли бы сделать
foo.by_key[key]
илиfoo.by_value[value]
. (Нет кода, поскольку он более сложный, и я ленивый, и я думаю, что это субоптимально.) -
В другой структуре, чтобы вы могли делать
d[key]
и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)
-
В той же структуре, что вы могли бы сделать
d[key]
и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)
(Заметно отсутствует в этих реализациях a bidict
метод update
, который будет немного более сложным (но help(dict.update)
укажет, что вам нужно будет покрыть). Без update
, bidict({1:2})
не будет делать то, на что он предназначен, и не будет d.update({1:2})
.)
Также рассмотрите вопрос о том, будет ли более подходящей другая структура данных.