Advertisement
Advertisement


Get key by value in dictionary


Question

I made a function which will look up ages in a Dictionary and show the matching name:

dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
for age in dictionary.values():
    if age == search_age:
        name = dictionary[age]
        print name

I know how to compare and find the age I just don't know how to show the name of the person. Additionally, I am getting a KeyError because of line 5. I know it's not correct but I can't figure out how to make it search backwards.

2018/04/01
1
660
4/1/2018 2:44:54 PM

Accepted Answer

There is none. dict is not intended to be used this way.

dictionary = {'george': 16, 'amber': 19}
search_age = input("Provide age")
for name, age in dictionary.items():  # for name, age in dictionary.iteritems():  (for Python 2.x)
    if age == search_age:
        print(name)
2020/03/30
575
3/30/2020 11:13:02 AM


If you want both the name and the age, you should be using .items() which gives you key (key, value) tuples:

for name, age in mydict.items():
    if age == search_age:
        print name

You can unpack the tuple into two separate variables right in the for loop, then match the age.

You should also consider reversing the dictionary if you're generally going to be looking up by age, and no two people have the same age:

{16: 'george', 19: 'amber'}

so you can look up the name for an age by just doing

mydict[search_age]

I've been calling it mydict instead of list because list is the name of a built-in type, and you shouldn't use that name for anything else.

You can even get a list of all people with a given age in one line:

[name for name, age in mydict.items() if age == search_age]

or if there is only one person with each age:

next((name for name, age in mydict.items() if age == search_age), None)

which will just give you None if there isn't anyone with that age.

Finally, if the dict is long and you're on Python 2, you should consider using .iteritems() instead of .items() as Cat Plus Plus did in his answer, since it doesn't need to make a copy of the list.

2011/11/05

I thought it would be interesting to point out which methods are the quickest, and in what scenario:

Here's some tests I ran (on a 2012 MacBook Pro)

>>> def method1(list,search_age):
...     for name,age in list.iteritems():
...             if age == search_age:
...                     return name
... 
>>> def method2(list,search_age):
...     return [name for name,age in list.iteritems() if age == search_age]
... 
>>> def method3(list,search_age):
...     return list.keys()[list.values().index(search_age)]

Results from profile.run() on each method 100000 times:

Method 1:

>>> profile.run("for i in range(0,100000): method1(list,16)")
     200004 function calls in 1.173 seconds

Method 2:

>>> profile.run("for i in range(0,100000): method2(list,16)")
     200004 function calls in 1.222 seconds

Method 3:

>>> profile.run("for i in range(0,100000): method3(list,16)")
     400004 function calls in 2.125 seconds

So this shows that for a small dict, method 1 is the quickest. This is most likely because it returns the first match, as opposed to all of the matches like method 2 (see note below).


Interestingly, performing the same tests on a dict I have with 2700 entries, I get quite different results (this time run 10000 times):

Method 1:

>>> profile.run("for i in range(0,10000): method1(UIC_CRS,'7088380')")
     20004 function calls in 2.928 seconds

Method 2:

>>> profile.run("for i in range(0,10000): method2(UIC_CRS,'7088380')")
     20004 function calls in 3.872 seconds

Method 3:

>>> profile.run("for i in range(0,10000): method3(UIC_CRS,'7088380')")
     40004 function calls in 1.176 seconds

So here, method 3 is much faster. Just goes to show the size of your dict will affect which method you choose.

Notes: Method 2 returns a list of all names, whereas methods 1 and 3 return only the first match. I have not considered memory usage. I'm not sure if method 3 creates 2 extra lists (keys() and values()) and stores them in memory.

2013/01/31

one line version: (i is an old dictionary, p is a reversed dictionary)

explanation : i.keys() and i.values() returns two lists with keys and values of the dictionary respectively. The zip function has the ability to tie together lists to produce a dictionary.

p = dict(zip(i.values(),i.keys()))

Warning : This will work only if the values are hashable and unique.

2020/05/13

a = {'a':1,'b':2,'c':3}
{v:k for k, v in a.items()}[1]

or better

{k:v for k, v in a.items() if v == 1}
2017/04/21

key = next((k for k in my_dict if my_dict[k] == val), None)
2020/03/31

Source: https://stackoverflow.com/questions/8023306
Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]