我对Python还不算很熟练,仍然在努力消化大量的信息。
我看到的所有关于字典的文档都解释了通过键获取值的各种方式 - 但是我正在寻找一种Pythonic的方法来通过值获取键。
我知道可以遍历键并检查其值,直到找到我要找的值,然后取得键,但我正在寻找一种直接的方法。
我对Python还不算很熟练,仍然在努力消化大量的信息。
我看到的所有关于字典的文档都解释了通过键获取值的各种方式 - 但是我正在寻找一种Pythonic的方法来通过值获取键。
我知道可以遍历键并检查其值,直到找到我要找的值,然后取得键,但我正在寻找一种直接的方法。
没有直接的路线。不过使用列表推导式相当容易;
[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
,只不过是相反的。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)
(这些实现中明显缺少一个 `bidict` 的 `update` 方法,这将稍微复杂一些(但是 `help(dict.update)` 将指出您需要覆盖的内容)。如果没有 `update`,`bidict({1:2})` 将无法实现其预期目的,`d.update({1:2})` 也是如此。)同样需要考虑其他数据结构是否更合适。由于您的字典可以包含重复的值(即{'a': 'A', 'b': 'A'}
),因此找到一个键对应的值的唯一方法是按照您所描述的那样迭代整个字典。
或者...构建相反的字典。在修改原始字典后,您必须重新创建它。
或者...编写一个维护双向字典的类。您将不得不处理出现重复值的情况。
使用列表推导式的第一种解决方案很好。
但是对于Python 3.x,需要进行一个小修复,将.iteritems()
替换为.items()
:
[k for k, v in d.items() if v == desired_value]
构建一个反向字典并不是一个好的方法,因为有一个或多个键可能具有相同的值,但如果你将其倒置,你需要插入键:[值1,... ]结构,这将导致另一个问题。