If I had someDictionary
defined as
{'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
and someList
defined as
[51, 52, 53, 54, 55, 56]
how can I find the key in someDictionary
that matches an element in someList
? For now, I'm assuming there won't be more than one match.
I would think it would be something like this:
for k, v in someDictionary.items():
if v == someList:
myAnswer = k
Given the code above, myAnswer
would be 3
The second part I need to do is, if someList does not contain an element that is in someDictionary
, find the value in someDictionary
larger than (but closest to) the last element in someList someList[-1]
In that case, myAnswer would be 6
It sounds like you want a bidict
>>> from bidict import bidict # pip install bidict
>>> d = bidict({'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60})
>>> d['3'] 55
>>> d.inv[55] '3'
This allows O(1) lookups in either direction. Now, you can loop over someList
and check if an element is in d.inv
efficiently.
First part, Find the list of keys that have a dictionary value in list.
someDictionary = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
someList = [51, 52, 53, 54, 55, 56]
res = [key for key, value in someDictionary.items() if value in someList]
second part, if no result from first part, find the key with the closest larger value (continuing):
if not res:
res = min ([(value, key) for key, value in someDictionary.items() if value > max(someList) ])[1]
myAnswer = ''
closest_to = someList[-1]
closest_diff = 0
for k in someDictionary:
if someDictionary[k] in someList:
myAnswer = k
break; # stop the loop when exact match found
diff = someDictionary[k] - closest_to
if diff > 0 and diff < closest_diff:
closest_diff = diff
myAnswer = k # this would save key of larger but closest number to last in someList
First use list comprehension to gather all keys whose values are in lst
, if there is no match then filter for keys whose value is larger than lst[-1]
. After sort them based on the abs value of the difference of the keys values and the last item in lst
and take the 0
index, closest item.
dct = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
lst = [51, 52, 53, 54, 55, 56]
my_answer = [int(i) for i in dct if dct[i] in lst]
if my_answer:
print(*my_answer) # => 3
else:
close = [i for i in dct if int(dct[i]) > max(lst)]
closest = sorted(close, key=lambda x: abs(dct.get(x) - lst[-1]))[0]
print(closest) # => 6
How can I find the key in
someDictionary
that matches an element insomeList
?
A dictionary is used map keys to values. The reverse isn't possible in O(1) time. But you can iterate in O( n ) time until you can match a list element with a dictionary value.
You can use a simple for
loop for this, either iterating your dictionary or list.
d = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
L = [51, 52, 53, 54, 55, 56]
def find_key_dict(d, L):
L_set = set(L) # convert to set for O(1) lookup
for k, v in d.items():
if v in L_set:
return k
def find_key_list(d, L):
d_rev = {v: k for k, v in d.items()} # reverse dict for value -> key map
for i in L:
if i in d_rev:
return d_rev[i]
find_key_dict(d, L) # '3'
find_key_list(d, L) # '3'
It's also possible to rewrite these functions as 1-line generator expressions with next
, but this won't necessarily be more efficient.
The second part I need to do is, if
someList
does not contain an element that is insomeDictionary
, find the value insomeDictionary
larger than (but closest to) the last element insomeList
You can write a similar function utilising a for... else...
construct with min
:
def find_key_dict(d, L):
L_set = set(L) # convert to set for O(1) lookup
for k, v in d.items():
if v in L_set:
return k
else:
def min_func(x):
diff = x[1] - L[-1]
return diff <= 0, diff
return min(d.items(), key=min_func)[0]
find_key_dict(d, L) # '6'
For the first question, you are just using the wrong operator to check if the value is in someList
for k, v in someDictionary.items():
if v in someList:
myAnswer = k
About the second question you can extend the previous code in this way
for k, v in someDictionary.items():
if v in someList:
myAnswer = k
break
else:
myAnswer = None
for k, v in someDictionary.items():
if v > someList[-1] and (myAnswer is None or v < someDictionary[myAnswer]):
myAnswer = k
If your dictionary and list are large, and especially if you have many lists to test against the same dictionary, it can be worth preparing your data in order to have a faster execution.
The worst operation in __init__
is sorting, which is O(n*log(n)). It allows us to use bisect
to find the closest value in your last case in O(log(n)).
from bisect import bisect
class FindInDict:
def __init__(self, someDictionary):
self.dict_by_values = {val: key for key, val in someDictionary.items()}
self.dict_values_set = set(sorted_values)
self.sorted_values = sorted(someDictionary.values())
def find(self, someList):
common = set(someList).intersection(self.dict_values_set)
if common:
key = self.dict_by_values[common.pop()]
else:
closest_value = self.sorted_values[bisect(self.sorted_values, someList[-1])]
key = self.dict_by_values[closest_value]
return key
someDictionary = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
finder = FindInDict(someDictionary)
finder.find([51, 52, 53, 54, 55, 56])
# 3
finder.find([51, 52, 53, 54, 56]) # no common value
# 6
Here's something that handles both parts of your question and should be easy to modify to handle any pesky "edge-cases" that might pop up:
someDictionary = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
someList = [51, 52, 53, 54, 55, 56]
myAnswer = [key for key in someDictionary if someDictionary[key] in someList]
if not myAnswer:
diffs = {dict_key: dict_value-someList[-1]
for dict_key, dict_value in someDictionary.items()
if dict_value-someList[-1] > 0}
myAnswer = [min(diffs, key=diffs.get)] # Key of value with minimum
# (positive) difference
print(myAnswer)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.