Inverse dictionary lookup in Python

2019-01-02 20:55发布

Is there any straightforward way of finding a key by knowing the value within a dictionary?

All I can think of is this:

key = [key for key, value in dict_obj.items() if value == 'value'][0]

14条回答
千与千寻千般痛.
2楼-- · 2019-01-02 21:13

There are cases where a dictionary is a one:one mapping

Eg,

d = {1: "one", 2: "two" ...}

Your approach is ok if you are only doing a single lookup. However if you need to do more than one lookup it will be more efficient to create an inverse dictionary

ivd = {v: k for k, v in d.items()}

If there is a possibility of multiple keys with the same value, you will need to specify the desired behaviour in this case.

If your Python is 2.6 or older, you can use

ivd = dict((v, k) for k, v in d.items())
查看更多
人间绝色
3楼-- · 2019-01-02 21:19

There is none. Don't forget that the value may be found on any number of keys, including 0 or more than 1.

查看更多
弹指情弦暗扣
4楼-- · 2019-01-02 21:22

There isn't one as far as I know of, one way however to do it is to create a dict for normal lookup by key and another dict for reverse lookup by value.

There's an example of such an implementation here:

http://code.activestate.com/recipes/415903-two-dict-classes-which-can-lookup-keys-by-value-an/

This does mean that looking up the keys for a value could result in multiple results which can be returned as a simple list.

查看更多
不再属于我。
5楼-- · 2019-01-02 21:22

I know this might be considered 'wasteful', but in this scenario I often store the key as an additional column in the value record:

d = {'key1' : ('key1', val, val...), 'key2' : ('key2', val, val...) }

it's a tradeoff and feels wrong, but it's simple and works and of course depends on values being tuples rather than simple values.

查看更多
冷夜・残月
6楼-- · 2019-01-02 21:22

As value could be non-existent in dict, a more pythonic and auto-documented code would be:

a  # Value to search against
x = None  # Searched key
for k, v in d.items():
    if v == a:
        x = k
        break
x  # Now contains the key or None if not found.

Indeed dicts aren't made to answer such problematics, if you encounter this problem on a new designed program then you should probably review your design.

查看更多
听够珍惜
7楼-- · 2019-01-02 21:28

This version is 26% shorter than yours but functions identically, even for redundant/ambiguous values (returns the first match, as yours does). However, it is probably twice as slow as yours, because it creates a list from the dict twice.

key = dict_obj.keys()[dict_obj.values().index(value)]

Or if you prefer brevity over readability you can save one more character with

key = list(dict_obj)[dict_obj.values().index(value)]

And if you prefer efficiency, @PaulMcGuire's approach is better. If there are lots of keys that share the same value it's more efficient not to instantiate that list of keys with a list comprehension and instead use use a generator:

key = (key for key, value in dict_obj.items() if value == 'value').next()
查看更多
登录 后发表回答