views:

267

answers:

6

Hi there,

is there any straight forward way of finding a key by knowing the value within a dictionary?

all I can think of is this:

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

Any ideas?

+3  A: 

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

Ignacio Vazquez-Abrams
+1  A: 

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.

Jon
Do note that there are many, many possible values that are not valid keys.
Ignacio Vazquez-Abrams
A: 

Through values in dictionary can be object of any kind they can't be hashed or indexed other way. So finding key by the value is unnatural for this collection type. Any query like that can be executed in O(n) time only. So if this is frequent task you should take a look for some indexing of key like Jon sujjested or maybe even some spatial index (DB or http://pypi.python.org/pypi/Rtree/ ).

Odomontois
A: 

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.

gnibbler
+2  A: 

Your list comprehension goes through all the dict's items finding all the matches, then just returns the first key. This generator expression will only iterate as far as necessary to return the first value:

key = (key for key,value in dd.items() if value=='value').next()

where dd is the dict. Will raise StopIteration if no match is found, so you might want to catch that and return a more appropriate exception like ValueError or KeyError.

Paul McGuire
A: 

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.

CarlS