在Python字典中从值查找键:
我刚接触Python,感觉信息量太大,有点吃力。
我看到的所有关于字典的文档都在讲怎么通过键来获取值,但我想找一种更“Python风格”的方法,反过来通过值来获取键。
我知道可以通过循环遍历所有的键,检查它们的值,直到找到我想要的值,然后再拿到对应的键,但我想要一种更直接的方法。
4 个回答
第一个用列表推导式的解决方案很好。不过对于Python 3.x,有个小修正,应该用.items()
,而不是.iteritems()
:
[k for k, v in d.items() if v == desired_value]
因为你的字典可以包含重复的值(比如 {'a': 'A', 'b': 'A'}
),所以要从值找到对应的键,唯一的方法就是像你说的那样一个一个遍历字典。
或者……你可以建立一个反向字典。每次修改原始字典后,你都得重新创建这个反向字典。
或者……你可以写一个类,来同时维护一个双向字典。这样的话,你需要处理出现重复值的情况。
没有直接的解决办法。不过,用列表推导式来做这件事其实挺简单的。
[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})
也是如此。
另外,考虑一下是否有其他数据结构更合适。