Reputation: 10793
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.
Upvotes: 987
Views: 2713069
Reputation: 1126
I was looking for this same question and I ended up with my variant:
found_key = [a[0] for a in dict.items() if a[1] == 'value'][0]
Only for those situations when a key has a unique value (which was my case).
Upvotes: 1
Reputation: 305
As someone mentioned there might be more than one key that have the same value, like my_dict
below. Moreover, there might be no matching key.
my_dict ={'k1':1,'k2':2, 'k3':1, 'k4':12, 'k5':1, 'k6':1, 'k7':12}
Here are three ways of finding a key, one for the last hit, and two for the first.
def find_last(search_value:int, d:dict):
return [x for x,y in d.items() if y==search_value].pop()
def find_first1(search_value:int, d:dict):
return next(filter(lambda x: d[x]==search_value, d.keys()), None)
def find_first2(search_value:int, d:dict):
return next(x for x,y in d.items() if y==search_value)
Of these find_first1
is a bit faster than the others, and will return None
in case there is no matching key.
Upvotes: 4
Reputation: 183
One line solution using list comprehension, which returns multiple keys if the value is possibly present multiple times.
[key for key,value in mydict.items() if value == 16]
Upvotes: 11
Reputation: 84
dict_a = {'length': 5, 'width': 9, 'height': 4}
# get the key of specific value 5
key_of_value = list(dict_a)[list(dict_a.values()).index(5)]
print(key_of_value) # length
# get the key of minimum value
key_min_value = list(dict_a)[list(dict_a.values()).index(sorted(dict_a.values())[0])]
print(key_min_value) # height
# get the key of maximum value
key_max_value = list(dict_a)[list(dict_a.values()).index(sorted(dict_a.values(), reverse=True)[0])]
print(key_max_value) # width
Upvotes: 1
Reputation: 2816
I found this answer very effective but not very easy to read for me.
To make it more clear you can invert the key and the value of a dictionary. This is make the keys values and the values keys, as seen here.
mydict = {'george':16,'amber':19}
res = dict((v,k) for k,v in mydict.iteritems())
print(res[16]) # Prints george
or for Python 3, (thanks @kkgarg)
mydict = {'george':16,'amber':19}
res = dict((v,k) for k,v in mydict.items())
print(res[16]) # Prints george
Also
print(res.get(16)) # Prints george
which is essentially the same that this other answer.
Upvotes: 48
Reputation: 2977
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(dict, search_age):
for name, age in dict.iteritems():
if age == search_age:
return name
def method2(dict, search_age):
return [name for name,age in dict.iteritems() if age == search_age]
def method3(dict, search_age):
return dict.keys()[dict.values().index(search_age)]
Results from profile.run()
on each method 100,000 times:
Method 1:
>>> profile.run("for i in range(0,100000): method1(dict, 16)")
200004 function calls in 1.173 seconds
Method 2:
>>> profile.run("for i in range(0,100000): method2(dict, 16)")
200004 function calls in 1.222 seconds
Method 3:
>>> profile.run("for i in range(0,100000): method3(dict, 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 10,000 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:
keys()
and values()
) and stores them in memory.Upvotes: 130
Reputation: 1004
This is kind of a strange question because the very first comment provides a perfect answer.
Based on the sample data example provided
dictionary = {'george': 16, 'amber': 19}
print(dictionary["george"])
It returns
16
So you want the opposite
to enter "16" and get "george"
So simply swap keys,values and presto
dictionary = {'george': 16, 'amber': 19}
inv_dict = {value:key for key, value in dictionary.items()}
print(inv_dict[16])
I was in the completely opposite position as i had a dictionary like
{16:'george', 19:'amber'}
and i was trying to feed "george" and get 16...i tried several kind of loops and iterators that OK..they work but it wasn't the easy one line solution that i would use for quick result...so i simply swapped and solution found.
If i missed something please let me know to delete my answer.
Upvotes: 4
Reputation: 165
Heres a truly "Reversible Dictionary", Based upon Adam Acosta's solution, but enforcing val-to-key calls to be unique and easily return key from value:
from collections import UserDict
class ReversibleDict(UserDict):
def __init__(self, enforce_unique=True, *args, **kwargs):
super().__init__(*args, **kwargs)
self.val_to_keys = {}
self.check_val = self.check_unique if enforce_unique else lambda x: x
def __setitem__(self, key, value):
self.check_val(value)
super().__setitem__(key, value)
self.val_to_keys[value] = key
def __call__(self, value):
return self.val_to_keys[value]
def check_unique(self, value):
assert value not in self.val_to_keys, f"Non unique value '{value}'"
return value
If you want to enforce uniqueness on dictionary values ensure to set enforce_unique=True. to get keys from values just do rev_dict(value), to call values from keys just do as usual dict['key'], here's an example of usage:
rev_dict = ReversibleDict(enforce_unique=True)
rev_dict["a"] = 1
rev_dict["b"] = 2
rev_dict["c"] = 3
print("full dictinoary is: ", rev_dict)
print("value for key 'b' is: ", rev_dict["b"])
print("key for value '2' is: ", rev_dict(2))
print("tring to set another key with the same value results in error: ")
rev_dict["d"] = 1
Upvotes: 1
Reputation: 431
I glimpsed all answers and none mentioned simply using list comprehension?
This Pythonic one-line solution can return all keys for any number of given values (tested in Python 3.9.1):
>>> dictionary = {'george' : 16, 'amber' : 19, 'frank': 19}
>>>
>>> age = 19
>>> name = [k for k in dictionary.keys() if dictionary[k] == age]; name
['george', 'frank']
>>>
>>> age = (16, 19)
>>> name = [k for k in dictionary.keys() if dictionary[k] in age]; name
['george', 'amber', 'frank']
>>>
>>> age = (22, 25)
>>> name = [k for k in dictionary.keys() if dictionary[k] in age]; name
[]
Upvotes: 5
Reputation: 603
I realize it's been a long time and the original asker likely no longer has any need of an answer, but none of these are good answers if you actually have control over this code. You're just using the wrong data structure. This is a perfect illustration of the use case for a two-way dict:
>>> from collections import defaultdict, UserDict
>>> class TwoWayDict(UserDict):
... def __init__(self, *args, **kwargs):
... super().__init__(*args, **kwargs)
... self.val_to_keys = defaultdict(list)
... def __setitem__(self, key, value):
... super().__setitem__(key, value)
... self.val_to_keys[value].append(key)
... def get_keys_for_val(self, value):
... return self.val_to_keys[value]
...
>>> d = TwoWayDict()
>>> d['a'] = 1
>>> d['b'] = 1
>>> d.get_keys_for_val(1)
['a', 'b']
Adds miniscule overhead to insertions but you keep constant-time lookup, except now in both directions. No need to construct the reverse mapping from scratch every time you need it. Just store it as you go and access it as needed.
Further, many of these answers are not even correct because clearly many people can have the same age but they're only returning the first matching key, not all of them.
Upvotes: 1
Reputation: 267
I ended up doing it with a function. This way you might avoid doing the full loop, and the intuition says that it should be faster than other solutions presented.
def get_key_from_value(my_dict, to_find):
for k,v in my_dict.items():
if v==to_find: return k
return None
Upvotes: 0
Reputation: 8098
my_dict = {'A': 19, 'B': 28, 'carson': 28}
search_age = 28
take only one
name = next((name for name, age in my_dict.items() if age == search_age), None)
print(name) # 'B'
get multiple data
name_list = [name for name, age in filter(lambda item: item[1] == search_age, my_dict.items())]
print(name_list) # ['B', 'carson']
Upvotes: 7
Reputation: 1441
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.
Upvotes: 89
Reputation: 129934
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)
Upvotes: 701
Reputation: 10083
mydict = {'george': 16, 'amber': 19}
print mydict.keys()[mydict.values().index(16)] # Prints george
Or in Python 3.x:
mydict = {'george': 16, 'amber': 19}
print(list(mydict.keys())[list(mydict.values()).index(16)]) # Prints george
Basically, it separates the dictionary's values in a list, finds the position of the value you have, and gets the key at that position.
More about keys()
and .values()
in Python 3: How can I get list of values from dict?
Upvotes: 1005
Reputation: 1063
we can get the Key
of dict
by :
def getKey(dct,value):
return [key for key in dct if (dct[key] == value)]
Upvotes: 15
Reputation: 61
for name in mydict:
if mydict[name] == search_age:
print(name)
#or do something else with it.
#if in a function append to a temporary list,
#then after the loop return the list
Upvotes: 6
Reputation: 3606
In my case the easiest way is to instantiate disctionary in your code then you can call keys from it like below
here is my class having dictionary
class Config:
def local(self):
return {
"temp_dir": "/tmp/dirtest/",
"devops": "Mansur",
}
To instantiate your dictionary
config = vars.Config()
local_config = config.local()
Finally calling your dictionary keys
patched = local_config.get("devops")
Upvotes: 0
Reputation: 1342
Just my answer in lambda
and filter
.
filter( lambda x, dictionary=dictionary, search_age=int(search_age): dictionary[x] == search_age , dictionary )
Upvotes: 4
Reputation: 1017
I tried to read as many solutions as I can to prevent giving duplicate answer. However, if you are working on a dictionary which values are contained in lists and if you want to get keys that have a particular element you could do this:
d = {'Adams': [18, 29, 30],
'Allen': [9, 27],
'Anderson': [24, 26],
'Bailey': [7, 30],
'Baker': [31, 7, 10, 19],
'Barnes': [22, 31, 10, 21],
'Bell': [2, 24, 17, 26]}
Now lets find names that have 24 in their values.
for key in d.keys():
if 24 in d[key]:
print(key)
This would work with multiple values as well.
Upvotes: 4
Reputation: 694
Try this one-liner to reverse a dictionary:
reversed_dictionary = dict(map(reversed, dictionary.items()))
Upvotes: 25
Reputation: 4437
dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
key = [filter( lambda x: dictionary[x] == k , dictionary ),[None]][0]
# key = None from [None] which is a safeguard for not found.
For multiple occurrences use:
keys = [filter( lambda x: dictionary[x] == k , dictionary )]
Upvotes: 1
Reputation: 189
Here, recover_key takes dictionary and value to find in dictionary. We then loop over the keys in dictionary and make a comparison with that of value and return that particular key.
def recover_key(dicty,value):
for a_key in dicty.keys():
if (dicty[a_key] == value):
return a_key
Upvotes: 7
Reputation: 160
Consider using Pandas. As stated in William McKinney's "Python for Data Analysis'
Another way to think about a Series is as a fixed-length, ordered dict, as it is a mapping of index values to data values. It can be used in many contexts where you might use a dict.
import pandas as pd
list = {'george':16,'amber':19}
lookup_list = pd.Series(list)
To query your series do the following:
lookup_list[lookup_list.values == 19]
Which yields:
Out[1]:
amber 19
dtype: int64
If you need to do anything else with the output transforming the answer into a list might be useful:
answer = lookup_list[lookup_list.values == 19].index
answer = pd.Index.tolist(answer)
Upvotes: 9
Reputation: 69
A simple way to do this could be:
list = {'george':16,'amber':19}
search_age = raw_input("Provide age")
for age in list.values():
name = list[list==search_age].key().tolist()
print name
This will return a list of the keys with value that match search_age. You can also replace "list==search_age" with any other conditions statement if needed.
Upvotes: 0
Reputation: 633
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}
Upvotes: 41
Reputation: 22051
You can get key by using dict.keys()
, dict.values()
and list.index()
methods, see code samples below:
names_dict = {'george':16,'amber':19}
search_age = int(raw_input("Provide age"))
key = names_dict.keys()[names_dict.values().index(search_age)]
Upvotes: 12
Reputation: 802
def get_Value(dic,value):
for name in dic:
if dic[name] == value:
del dic[name]
return name
Upvotes: 3