This question already has answers here:
Get key by value in dictionary
(43 answers)
Closed 8 years ago.
If p='hello'
I need to search the dictionary for the value 'hello' and return the key for 'hello'
Is there a certain built in function that could help me do this?
I can't think of a built-in function to do this, but the best possible way would be:
def get_keys(d, x):
return [k for k, v in adict.items() if v == x]
Demo:
>>> example = {'baz': 1, 'foo': 'hello', 'bar': 4, 'qux': 'bye'}
>>> get_keys(example, 'hello')
['foo']
We use a list here because any one value can occur multiple times in a dictionary- so we need something to hold all of the applicable corresponding keys.
With that in mind, if you only want the first found instance you would just do [0] on the returned list.
You can do:
def get_pos(my_dict, my_str):
pos = []
for i in my_dict:
if my_dict[i] == my_str:
pos.append(i)
return pos
Examples
>>> a = {'apple':'hello', 'banana':'goodbye'}
>>> get_pos(a,'hello')
'apple'
Related
This question already has answers here:
How can I remove a key from a Python dictionary?
(11 answers)
Closed 8 years ago.
Is there an easy way to delete a property of a dictionary in Python when it is possible that the property may not be present to begin with?
if the del statement is used, a KeyError is the result:
a = {}
del a['foo']
>>>KeyError: 'foo'
Its a little wordy to use an if statement and you have to type 'foo' and a twice :
a = {}
if 'foo' in a:
del a['foo']
Looking for something similar to dict.get() that defaults to a None value if the property is not present:
a = {}
a.get('foo') # Returns None, does not raise error
You can use dict.pop, which allows you to specify a default value to return if the key does not exist:
>>> d = {1:1, 2:2}
>>> d.pop(1, None)
1
>>> d
{2: 2}
>>> d.pop(3, None) # No error is thrown
>>> d
{2: 2}
>>>
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm trying to find the key when searching a dictionary list of keys. But the string is not an exact match to the dictionary keys. This is what i have so far:
if string in d.keys():
print 'found'
I would like the key that was found.
I don't think there is anything better than a linear scan across d's keys.
print [k for k in d if string in k]
If this is something your program relies on a lot, you could do this:
class ApproxDict(dict):
def __contains__(self, item):
# item contains the key. Do what you need with it.
return True # or False again this depends on what you want
Using either of the other solutions suggested to implement the __contains__() method.
That way you have your customized lookup and retain the readability of python.
For key substring lookup as you precised in your comment:
>>> class ApproxDict(dict):
... def __contains__(self, item):
... for key in self.keys():
... if item in key:
... return True
... return False
...
>>> d = ApproxDict()
>>> d['abc123'] = "some value"
>>> 'bc1' in d
True
>>> 'bc2' in d
False
>>>
See the python data model documentation.
Hope that helps.
By the way, with a dictionnary:
if key in d:
# whatever
is equivalent to:
if key in d.keys():
# whatever
Let's say that distance compares two strings and returns a lower number if the strings are a good match and a higher number when the strings are a bad match. (You have to decide what to employ there, Levenshtein, etc).
bestMatch = None
value = None
for k, v in d.items ():
match = distance (k, searchedKey)
if bestMatch == None or bestMatch > match:
bestMatch = match
value = v
print (value) # the value of the best matched key
If I'm understanding your question correctly, you want to fuzzy string match with the keys. Here's what I suggest:
>>> keys = ["apple", "plum", "pear", "carrot"]
>>> d = {key:val for key, val in zip(keys,range(4))}
>>> d
{'plum': 1, 'carrot': 3, 'pear': 2, 'apple': 0}
>>>
>>> searchKey = "aple"
>>>
>>> import difflib
>>>
>>> try:
... searchVal = d[searchKey]
... except:
... closeKey = difflib.get_close_matches(searchKey, d.keys(), 1)[0]
... searchVal = d[closeKey]
...
>>> searchVal
0
This question already has answers here:
partial match dictionary key(of tuples) in python
(4 answers)
Closed 8 years ago.
d = dict({('a','b'):1})
then how to get value by using either d.get('a') or d.get('b') instead of d.get(('a','b'))
>>> d=dict({('a','b'):1})
>>> d.get('a') // should return value as 1
>>> d.get('b') // should return value as 1
>>> d.get(('a','b'))
1
>>>
You could make a partial match function similar to, but simpler than, the one in this question.
def partial_match(d, part_key):
for key, value in d.items():
if part_key in key:
return value
>>> partial_match(d, 'a')
1
You could create a dedicated data structure derived from dict:
>>> class MyDict(dict):
... def __init__(self, *args):
... if args and type(args[0]) is dict:
... for k, v in args[0].iteritems():
... self.__setitem__(k, v)
... dict.__init__(self, *args)
... def __setitem__(self, keys, val):
... dict.__setitem__(self, keys, val)
... if type(keys) is tuple:
... for k in keys:
... self.__setitem__(k, val)
...
>>> d=MyDict({('a','b'):1})
>>> print d.get('a')
1
>>> print d.get('b')
1
>>> print d.get(('a','b'))
1
>>>
This creates new entries in the dictionary as suggested by #Thrustmaster.
The alternative is to create a 'partial match' function as #Stuart has proposed, that uses less memory as entries are not duplicated, but using more computations as it requires looping through all keys, effectively making the key hashes useless.
As pointed out in the comments, dictionary is simply a key-value mapping. You give it a single key, it will return a uniquely identifiable value against it.
To be able to get the value from the dict using any of the elements in the tuple, then you'd need to use something like the below:
>>> def updateDict(d, obj):
... for key, value in obj.items():
... for k in key:
... d[k] = value
...
>>> res = {}
>>> updateDict(res, {('a','b'):1})
>>> res
{'a': 1, 'b': 1}
>>> res['a']
1
>>> res['b']
1
Note that the code above merely inserts the values multiple time one for each element in the tuple.
You can create the dictionary you want using the original dict:
d1 = dict({('a','b'):1})
# creates {'a':1, 'b':1 }
d2 = {x:v for k, v in d1.items() for x in k}
print d2.get('a') # prints 1
print d2.get('b') # prints 1
This question already has answers here:
sort dict by value python [duplicate]
(9 answers)
Closed 9 years ago.
I have a list, and it is currently sorted by key(A,B,C). The value is a number count of how many times the key appears in a file. The code gives results like this:
14 A
157 B
17 C
...
I need to reverse this order around. I want to sort by the value instead of key so it reads like this:
14 A
17 C
157 B
I have read and tried all the documentation I could find on here and Google. I don't think it should be too complex, but I am overthinking something.
Is there a simple solution to read the order by number value? Also every time I try to sort by value, it says 'int or str is not callable'. I don't understand what this means.
Some of my code is below:
lst = list()
for key, val in counts.items():
lst.append((key, val))
lst.sort()
for key, val in lst:
print val, key
The key argument to sort() allows you to specify the sorting key.
You could use:
lst.sort(key=lambda (k,v):v)
or, equivalently,
lst.sort(key=operator.itemgetter(1))
list.sort accept optional key parameter.
>>> counts = {
... 'A': 14,
... 'B': 157,
... 'C': 17,
... }
>>>
>>> lst = counts.items()
>>> lst.sort(key=lambda x: x[1]) # x[1] => count
>>> for key, val in lst:
... print val, key
...
14 A
17 C
157 B
According to Mutable Sequence Types:
The sort() method takes optional arguments for controlling the comparisons.
...
key specifies a function of one argument that is used to extract a
comparison key from each list element: key=str.lower. The default
value is None.
This works, assuming
import operator
for key, val in counts.items():
lst.append((key, val))
# lst should be like this :
# lst = [('A',14), ('B',157), ('C',17), ('D',12), ('E',189)]
sorted_lst = sorted(set(lst), key=operator.itemgetter(1))
print sorted_lst
This question already has answers here:
Checking a nested dictionary using a dot notation string "a.b.c.d.e", automatically create missing levels
(5 answers)
How can I return a default value for an attribute? [duplicate]
(7 answers)
Closed 8 years ago.
I have a document like this:
>>> k = {'finance_pl':{'S':{'2008':45,'2009':34}}}
Normal way to access is:
>>> k['finance_pl']['S']
{'2008': 45, '2009': 34}
But, in my case the end user will give me input as finance_pl.S
I can split this and access the dictionary like this:
>>> doc_list = doc.split('.')
>>> k[doc_list[0]][doc_list[1]]
{'2008': 45, '2009': 34}
But, I don't want to do this, since the dictionary structure may change the and
user can give something like this finance_pl.new.S instead of k['finance_pl']['S'] or k[doc_list[0]][doc_list[1]].
I need something to apply the users input directly (Ex: if input is finance_pl.new.S, I should be able to apply this .split('.') method to the users input and apply directly).
What is the elegant way to do that ?
I'd simply loop over all the parts:
def getter(somedict, key):
parts = key.split(".")
for part in parts:
somedict = somedict[part]
return somedict
after which we have
>>> getter(k, "finance_pl.S")
{'2008': 45, '2009': 34}
or
>>> getter({"a": {"b": {"c": "d"}}}, "a")
{'b': {'c': 'd'}}
>>> getter({"a": {"b": {"c": "d"}}}, "a.b.c")
'd'
You could go for something like:
k = {'finance_pl':{'S':{'2008':45,'2009':34}}}
print reduce(dict.__getitem__, 'finance_pl.S.2009'.split('.'), k)
# 34
If you're using Python 3.x, you'll need a from functools import reduce in there...
>>> k = {'finance_pl':{'S':{'2008':45,'2009':34}}}
>>> ui = 'finance_pl.S'
>>> def getter(adict, key):
... return reduce(dict.get, key.split('.'), adict)
...
>>> getter(k, ui)
{'2008': 45, '2009': 34}
>>>
userkey = 'finance_pl.new.S'
for key in userkey.split('.'):
k = k[key]
# the final value of k is the one you want
So basically just iterate on every subkey and retrieve the inner dictionary until you're out of subkeys