在Python字典中通过值找到键:

16

我对Python还不算很熟练,仍然在努力消化大量的信息。

我看到的所有关于字典的文档都解释了通过键获取值的各种方式 - 但是我正在寻找一种Pythonic的方法来通过值获取键。

我知道可以遍历键并检查其值,直到找到我要找的值,然后取得键,但我正在寻找一种直接的方法。

4个回答

31

没有直接的路线。不过使用列表推导式相当容易;

[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})` 也是如此。)同样需要考虑其他数据结构是否更合适。

“其他数据结构”,如果我想要双向操作,类似于:key->value|value->key,你有什么建议?对于我来说,Python 中有太多新的信息,我还没有很好地适应。 - Vector
1
@Mikey:考虑使用的数据结构涉及更多的架构考虑;不要只考虑键值、值键,而是考虑其他方式来实现你想要的结果。我的意思是像图形、列表或集合这样的东西可能更合适。有很多可以使用的数据结构。如果不知道你想要实现什么,我就不能做更多了。 - Chris Morgan
我习惯使用'indexOf',或者使用内置支持我所做的事情的组件 - 从列值获取PK值 - 所以我没有太多考虑。与此同时,反向字典对我很有用,这只是我为自我教育而做的一个小测试应用程序。谢谢。 - Vector

6

由于您的字典可以包含重复的值(即{'a': 'A', 'b': 'A'}),因此找到一个键对应的值的唯一方法是按照您所描述的那样迭代整个字典。

或者...构建相反的字典。在修改原始字典后,您必须重新创建它。

或者...编写一个维护双向字典的类。您将不得不处理出现重复值的情况。


建立相反的字典 - 那就是我最终所做的,但我正在寻找更清晰的方法。 - Vector

1

使用列表推导式的第一种解决方案很好。 但是对于Python 3.x,需要进行一个小修复,将.iteritems()替换为.items()

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

0

构建一个反向字典并不是一个好的方法,因为有一个或多个键可能具有相同的值,但如果你将其倒置,你需要插入键:[值1,... ]结构,这将导致另一个问题。


问题不在于构建这样的字典。 - Vector

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接