check if numeric element is in an interval key dictionary in python - python

from the following dictionary with tuple as keys and a string as value:
dict_interval = {(1,5):"foo",(5,100):"bar"}
by using the dict, how would be possible to use a function with the following behaviour?
age = 4
categorizer(age, dict_interval)
gives the following output:
"foo"

If you expect age to be within multiple intervals and you want to get them all:
# Categoriser, returns a list
def categoriser(age, d) -> list:
return [value for key, value in d.items()
if is_between(age, key)]
# Helper function
def is_between(value, interval):
return interval[0] <= value < interval[1]
I have added an overlapping interval to your data
>>> dict_interval = {(1,5): "foo", (2, 5): "foo2", (5,100): "bar"}
>>> categoriser(4, dict_interval)
["foo", "foo2"]
If you want the first value only:
# Categoriser, returns first value
def categoriser(age, d) -> str:
for key, value in d.items():
if is_between(age, key):
return value
>>> categoriser(4, dict_interval)
"foo"

If you want all the values where the age is in the interval you can use the following code:
def get_all_values(age):
res = []
for key, value in dict_interval .items():
if (age >= key[0] and age <= key[1]):
res.append(value)
return res
this function will return a list of all the correct values. If you can only get 1 correct value you can do it like that:
def get_value(age):
for key in dict_interval .keys():
if (age >= key[0] and age <= key[1]):
return dict_interval[key]

def categorizer(value, dict_interval):
for k in dict_interval:
if k[0] < value < k[1]:
return(dict_interval[k])
This should work, assuming that key is unique I guess.

Related

Python return key of dictionary depending on max value, but only where part of key = x

I have a dictionary in Python:
dict = {("s1", "a1"):1,("s1", "a2"):2,("s3", "a3"):3,("s1", "a3"):1}
Where key is a list(s, a) and value is an integer, so:
dict = {(s, a), i}
I want to pass in a specific s and return a where i is highest.
In the example above, I would expect to recieve "a2" if I passed in "s1".
So far I have the following:
print(max(dict, key=dict.get("s1"))[1])
However this is returning s3. How do I get this to work?
I would filter the dictionary first to only get items with a valid key and then find the key with the maximum value like this:
filtered_dict = {k:v for k, v in d.items() if k[0] == 's1'}
result = max(filtered_dict, key=filtered_dict.get)[1]
print(result)
Output:
a2
The structure of the data is not the ideal one for your given use-case. But if you have no other option, you need to visit every single element in the dict.
You visit each element once:
current_max = -999
result = None
for (k1,k2), value in dict.items():
if k1=="s1" and value > current_max:
result = k2
current_max = value

I am trying to search a value and get its key as the output

a = {1897:("Diptojit", "Sealdah", 9000000001),
2224:("Debanjan", "Tarakeshwar", 9000000002),
1758: ("Avinesh", "Metropolitan", 9000000003),
2283: ("Biswajit", "Garia", 9000000004)}
n = input("Enter name to know index : ")
lk = list(a.keys())
lv = list(a.values())
#print(lv[0])
for i in range(0,4):
if n == "('Biswajit', 'Garia', 9000000004)":
print(lk[lv.index(n)])
break
I am trying to search a value and get its key as the output. This program shows no output while in case of a simple dictionary, when all keys have just one value, this code works perfectly.
Please Help.
You can do the following:
import ast
...
...
for i,j in a.items():
if ast.literal_eval(n) == j:
print(i)
ast.literal_eval safely evaluates the tuple since it is a string representation of the tuple. Then zip the lists containing keys and values and then check if that is equal to j
You could iterate over every key value pair in the dictionary, and if the value matches the value you are finding, then you return the key. The method dict.items() returns us an array of key value pairs, and we can iterate the array to find the value we want.
Eg:
def get_key_from_value(d, search_value):
for key, value in d.items(): # (("a", 1), ("b", 2), ("c", 3))
if value == search_value:
return key
return None
d = {"a": 1, "b": 2, "c": 3}
search_value = 2
key = get_key_from_value(d, search_value) # returns "b"
Edit:
dict.items() returns an array of key value pairs, which we then destructure in the for loop as key and value. Then, for each iteration we compare it to the value we are searching for, and if it is the correct value, we return the key. If it isn't found, it returns None.
To learn more about python destructuring: https://blog.teclado.com/destructuring-in-python/
Use ast.literal_eval() or eval() (former is preferred [read why] though latter is part of the standard library) to convert input to tuple and match objects. Check out the following piece of code:
a = {1897:("Diptojit", "Sealdah", 9000000001),
2224:("Debanjan", "Tarakeshwar", 9000000002),
1758: ("Avinesh", "Metropolitan", 9000000003),
2283: ("Biswajit", "Garia", 9000000004)}
try: n = eval(input("Enter name to know index : ")) # converts input string to tuple for matching.
except: print("Invalid input format.")
for idx, details in a.items():
if n == details:
print(idx)
break
I have modified your code logic to work for generalized inputs.
Example input: Enter name to know index : ("Avinesh", "Metropolitan", 9000000003)
Example output: 1758

dictionary value compare and reassign

I want to solve a itenary problem, travel schedule. Here is my existing code.
import array as arr
class Solution():
def __init__(self):
pass
def printItenary(self,d):
reverse_d = dict()
for i in d:
if i and d[i]:
reverse_d[d[i]] = i
else:
print("Innvalid Input")
return
for i in reverse_d:
if reverse_d[i] not in reverse_d:
starting_pt = reverse_d[i]
break;
while(starting_pt in d):
print(starting_pt,"->",d[starting_pt],end=", ")
starting_pt = d[starting_pt]
if __name__=="__main__":
d = dict()
d["Chennai"] = "Banglore"
d["Bombay"] = "Delhi"
d["Goa"] = "Chennai"
d["Delhi"] = "Goa"
obj = Solution()
obj.printItenary(d)
The problem is if I add another line,
d["Chennai"] = "Delhi"
then there are multiple values for a single item, so i want to give a condition, if multiple inputs are given, then I will give priority based on lexicographical order, except it is not the value is in a dead end(if it is the last stoppage).
So my problem is, how to compare the dictionary data and update the value based on those condition
You need to make sure you handle the edge case of the key not being present. If you want it case insensitive, then do str.lower() as well in the comparison.
new_val = ...
val = d.get('Chennai')
val = min(val, new_val) if val else new_val
d['Chennai'] = val
For determining lexicographical order you could use the ord() function; ord('b') > ord('a') == True
if d["Chennai"]:
if ord(new_value[0]) > ord(d["Chennai"][0]):
d["Chennai"] = new_value
else:
d["Chennai"] = new_value

Use python function to get key by value in dictionary and return either key or "None'

I am trying to return only the key value '20' but instead my function returns 'None'. I only want it to return None if value is not in my input dictionary.
def find_key(input_dict, value):
for key,val in input_dict.items():
if val == value:
return key
else:
return "None"
find_key({100:'a', 20:'b', 3:'c', 400:'d'}, 'b')
You can revise your function to be
def find_key(input_dict, value):
for key, val in input_dict.items():
if val == value: return key
return "None"
which means the function only returns the string "None" if the loop has already ended. In your original version, the loop will exit after the first iteration because it hits a return keyword. Also, if you are returning special Python None instead of a string "None", you don't even need to return anything explicitly because None is the default return value of a function without a return keyword.
This returns the first matched key or None:
def find_key(input_dict, value):
result = "None"
for key,val in input_dict.items():
if val == value:
result = key
return result
key = find_key({100:'a', 20:'b', 3:'c', 400:'d'}, 'b')
print(key) # 20
Because you don't know if your dictionary has multiple values like the one you're looking for, you should consider returning a list of keys.
Also, returning 'None' is probably a mistake, you should consider returning None (not a string with the word 'None', but the actual None value), which is more useful in Python.
As a result, I'd use:
def find_keys(d, value):
result = [key for key, x in d.items() if x == value]
return result if result else None
Or, since [] is pretty clear if you're returning a list, simply:
def find_keys(d, value):
return [key for key, x in d.items() if x == value]
Apart from covering all cases, I like this solution the best because if you read the code out loud, it's pretty obvious what it does, as well as performing well.
value_key_dict = {value: key for key, value in dic7.items()}
searched_key = value_key_dict[any_value]

recursive function find the max value on python

I am stuck my code. I want to find recursive max value.
here is my goal
1.If more than one element maximises the key, then the first one (the one that comes earliest in the array) must be returned.
2.The key parameter must be optional; if not provided, the function must return the (first) largest element. Think of a good default value for the key function!
3.Do not use the built-in max or min functions (obviously).
here is my code!
def recursive_max(seq, key):
if len(seq) == 1:
return seq[0]
else:
key = recursive_max(seq[1:])
if key > seq[0]:
return key
else:
return seq[0]
print(recursive_max(range(-5, 5 + 1))) #answer is 5
print(recursive_max(range(-5, 5 + 1), lambda x: x * x)) #answer is -5
class PoliticalDivision:
def __init__(self, name, area):
self.name = name
self.area = area
divisions = [
PoliticalDivision("Brazil", 8.5),
PoliticalDivision("China", 9.5),
PoliticalDivision("New Zealand", 0.27),
PoliticalDivision("Russia", 17),
PoliticalDivision("UK", 0.24),
PoliticalDivision("US", 9.5),
]
print(recursive_max(divisions, lambda division: division.area).name) #answer is Russia.
I just cant get ritht output.
even another code is
def recursive_max(seq, key=lambda x: x):
if len(seq) == 1:
return seq[0]
else:
return max(seq[0], recursive_max(seq[1:], key), key=key)
the feedback is Runtime error
File "prog.python3", line 5, in recursive_max
return max(seq[0], recursive_max(seq[1:], key), key=key)
how to improve it ?
any suggestions will be glad :)
Consider:
def recursive_max(seq, key=None):
# if key isn't given, call it again with key being returning the value itself
if not key: return recursive_max(seq, lambda a: a)
# error checking: can't get max of empty sequence
if not seq: raise ValueError("max of empty seq")
# base case: seq of 1, the max is the first element
if len(seq) == 1: return seq[0]
# get the max of the rest of the list
sub_max = recursive_max(seq[1:], key)
# if that's bigger than 1st element, return that, else return 1st element
return sub_max if key(sub_max) > key(seq[0]) else seq[0]

Categories

Resources