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
Related
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.
How can I check that my dict contains only one value filled ?
I want to enter in my condition only if the value is the only one in my dict and of this type (in my example "test2") of my dict.
For now I have this if statement
my_dict = {}
my_dict["test1"] = ""
my_dict["test2"] = "example"
my_dict["test3"] = ""
my_dict["test4"] = ""
if my_dict["test2"] and not my_dict["test1"] and not my_dict["test3"] and not my_dict["test4"]:
print("inside")
I would like to find a better, classy and "pep8" way to achieve that
Any ideas ?
You have to check every value for truthiness, there's no way around that, e.g.
if sum(1 for v in my_dict.values() if v) == 1:
print('inside')
You can use filter() as below to check how many values are there in the dictionary.
if len(list(filter(None, my_dict.values()))) == 1:
print("inside")
Assuming that all your values are strings, what about
ref_key = "test2"
if ''.join(my_dict.values()) == my_dict[ref_key]:
print("inside")
... since it looks like you have a precise key in mind (when you do if my_dict["test2"]). Otherwise, my answer is (twice) less general than (some) others'.
Maybe you want to check if there's only one pair in dictionary after removing the empty values.
my_dict = {}
my_dict["test1"] = ""
my_dict["test2"] = "example"
my_dict["test3"] = ""
my_dict["test4"] = ""
my_dict={key:val for key,val in my_dict.items() if val}
if len(my_dict)==1:
print("inside")
Here is the another flavour (without loops):
data = list(my_dict.values())
if data.count('') + 1 == len(data):
print("Inside")
I want to search through a list of objects for the lowest number present in an attribute of the objects.
This is easy enough using a list comprehension and the min function. The issue comes when I want to find the index of the object.
class School:
def __init__(self, name, num_pupils, num_classrooms):
self.name = name
self.num_pupils = num_pupils
self.num_classrooms = num_classrooms
def students_per_class(self):
return self.num_pupils / self.num_classrooms
def show_info(self):
print(f"{self.name} has {self.students_per_class():.2f} students per class.")
def string_checker(question):
valid = False
while not valid:
try:
response = str(input(question))
if all(character.isalpha() or character.isspace() for character in response):
valid = True
return response
else:
print("Enter a string containing no numbers of special characters. ")
except ValueError:
print("Enter a string containing no numbers of special characters. ")
def num_checker(question):
valid = False
while not valid:
try:
response = int(input(question))
if (response):
valid = True
return response
else:
print("Enter an integer containing no letters or special characters. ")
except ValueError:
print("Enter an integer containing no letters or special characters. ")
def new_school():
school_name = string_checker("School Name: ")
num_pupils = num_checker("Number of Pupils: ")
num_classrooms = num_checker("Number of Classrooms: ")
return School(school_name, num_pupils, num_classrooms)
if __name__ == "__main__":
schools = []
school = School("Darfield High School", 900, 37)
schools.append(school)
school.show_info()
for i in range(1):
schools.append(new_school())
for school in schools:
school.show_info()
print(min(school.students_per_class() for school in schools))
# This works fine and prints the value of the lowest number
print(schools.index(min(school.students_per_class() for school in schools)))
# This doesn't work as it tries to find the index of the value returned
# from the min function as it should.
You can use min's key argument to search by index:
index = min(range(len(schools)), key=lambda i: schools[i].students_per_class())
print(schools[index])
A key provides the values that will be compared instead of the actual sequence. Here, my sequence is range(len(schools)), which is just the indices of all the elements. But instead of finding the minimum index, I am making it so that we find the minimum of schools[i].students_per_class() for each index i.
If you wanted to be able to compare, sort, find the min/ max on the items directly you could use the "dunder" methods. These methods allow you to overload built in functions on classes.
For instance if you had a class like this
class Item:
def __init__(self, value):
self.value = value
def __lt__(self, other):
return self.value < other.value
def __eq__(self, other):
return self.value == other.value
You can then create two instances and compare them directly like this,
A = Item(1)
B = Item(2)
print(A < B) # Prints True
or if you had a list of items
items = [A, B]
You can then get the minimum item by going
min_item = min(items)
or the index of it by going
min_item_index = items.index(min(items))
although it may be enough to just have a reference to the minimum item.
Use enumerate to iterate through lists while keeping track of indices:
min(((i, school.students_per_class()) for i, school in enumerate(schools)), key=lambda x: x[1])
(i, school.students_per_class()) is a tuple and using key parameter of min(), we ask Python to find minimum of school.students_per_class(), which subsequently returns it's index along with it.
Read about lambda here.
I think you may be looking for np.argmin function, if you provide a list as an input it will return the index of the minimal element.
in this case it would be:
import numpy as np
min_ind = np.argmin([school.students_per_class() for school in schools])
print(schools[min_ind])
#Tomas Ordonez
Your answer is here:
def minInt(instanceList):
sorted_instanceList = sorted(instanceList, key=lambda instance: instance.int)
minIndex = instanceList.index(sorted_instanceList[0])
return minIndex
Hi i have a simple function:
def check_val(value):
if value < 10:
previous = value
return previous
else:
current = value + 10
return current
a = check_val(3)
How can I know if current or previous was returned?
You can have your function return a tuple with the necessary meta and unpack via sequence unpacking:
def check_val(value):
if value < 10:
previous = value
return previous, 'previous'
else:
current = value + 10
return current, 'current'
a, b = check_val(3)
print(a, b)
3 previous
You can't unless you return a tuple with a flag specifying where you exited
def check_val(val):
if value < 10:
previous = value
return previous, False
else:
current = value + 10
return current, True
a, was_current = check_val(3)
print(a, was_current) # --> 3 False
Well, first of all, you can't do this directly. There is no way of telling which return sent you the value just from the value itself.
You can of course return a tuple, as pointed out within other answers.
In my oppinion though, you should try to decouple checks from other calculations if you are interested in both informations, for it makes it easier to understand the returned value.
Like that, maybe:
def check_condition(value):
if value < 10:
return True
return False
def get_result(value, condition):
if condition:
return value
else:
return value + 10
val = 5
check_result = check_condition(val)
result = get_result(val, check_result)
It's hard to say if that makes sense since I don't know your use case. In your particular example I'd probably stick to the tuple.
I am trying to find corresponding keys in two different dictionaries. Each has about 600k entries.
Say for example:
myRDP = { 'Actinobacter': 'GATCGA...TCA', 'subtilus sp.': 'ATCGATT...ACT' }
myNames = { 'Actinobacter': '8924342' }
I want to print out the value for Actinobacter (8924342) since it matches a value in myRDP.
The following code works, but is very slow:
for key in myRDP:
for jey in myNames:
if key == jey:
print key, myNames[key]
I've tried the following but it always results in a KeyError:
for key in myRDP:
print myNames[key]
Is there perhaps a function implemented in C for doing this? I've googled around but nothing seems to work.
Thanks.
Use sets, because they have a built-in intersection method which ought to be quick:
myRDP = { 'Actinobacter': 'GATCGA...TCA', 'subtilus sp.': 'ATCGATT...ACT' }
myNames = { 'Actinobacter': '8924342' }
rdpSet = set(myRDP)
namesSet = set(myNames)
for name in rdpSet.intersection(namesSet):
print name, myNames[name]
# Prints: Actinobacter 8924342
You could do this:
for key in myRDP:
if key in myNames:
print key, myNames[key]
Your first attempt was slow because you were comparing every key in myRDP with every key in myNames. In algorithmic jargon, if myRDP has n elements and myNames has m elements, then that algorithm would take O(n×m) operations. For 600k elements each, this is 360,000,000,000 comparisons!
But testing whether a particular element is a key of a dictionary is fast -- in fact, this is one of the defining characteristics of dictionaries. In algorithmic terms, the key in dict test is O(1), or constant-time. So my algorithm will take O(n) time, which is one 600,000th of the time.
in python 3 you can just do
myNames.keys() & myRDP.keys()
for key in myRDP:
name = myNames.get(key, None)
if name:
print key, name
dict.get returns the default value you give it (in this case, None) if the key doesn't exist.
You could start by finding the common keys and then iterating over them. Set operations should be fast because they are implemented in C, at least in modern versions of Python.
common_keys = set(myRDP).intersection(myNames)
for key in common_keys:
print key, myNames[key]
Best and easiest way would be simply perform common set operations(Python 3).
a = {"a": 1, "b":2, "c":3, "d":4}
b = {"t1": 1, "b":2, "e":5, "c":3}
res = a.items() & b.items() # {('b', 2), ('c', 3)} For common Key and Value
res = {i[0]:i[1] for i in res} # In dict format
common_keys = a.keys() & b.keys() # {'b', 'c'}
Cheers!
Use the get method instead:
for key in myRDP:
value = myNames.get(key)
if value != None:
print key, "=", value
You can simply write this code and it will save the common key in a list.
common = [i for i in myRDP.keys() if i in myNames.keys()]
Copy both dictionaries into one dictionary/array. This makes sense as you have 1:1 related values. Then you need only one search, no comparison loop, and can access the related value directly.
Example Resulting Dictionary/Array:
[Name][Value1][Value2]
[Actinobacter][GATCGA...TCA][8924342]
[XYZbacter][BCABCA...ABC][43594344]
...
Here is my code for doing intersections, unions, differences, and other set operations on dictionaries:
class DictDiffer(object):
"""
Calculate the difference between two dictionaries as:
(1) items added
(2) items removed
(3) keys same in both but changed values
(4) keys same in both and unchanged values
"""
def __init__(self, current_dict, past_dict):
self.current_dict, self.past_dict = current_dict, past_dict
self.set_current, self.set_past = set(current_dict.keys()), set(past_dict.keys())
self.intersect = self.set_current.intersection(self.set_past)
def added(self):
return self.set_current - self.intersect
def removed(self):
return self.set_past - self.intersect
def changed(self):
return set(o for o in self.intersect if self.past_dict[o] != self.current_dict[o])
def unchanged(self):
return set(o for o in self.intersect if self.past_dict[o] == self.current_dict[o])
if __name__ == '__main__':
import unittest
class TestDictDifferNoChanged(unittest.TestCase):
def setUp(self):
self.past = dict((k, 2*k) for k in range(5))
self.current = dict((k, 2*k) for k in range(3,8))
self.d = DictDiffer(self.current, self.past)
def testAdded(self):
self.assertEqual(self.d.added(), set((5,6,7)))
def testRemoved(self):
self.assertEqual(self.d.removed(), set((0,1,2)))
def testChanged(self):
self.assertEqual(self.d.changed(), set())
def testUnchanged(self):
self.assertEqual(self.d.unchanged(), set((3,4)))
class TestDictDifferNoCUnchanged(unittest.TestCase):
def setUp(self):
self.past = dict((k, 2*k) for k in range(5))
self.current = dict((k, 2*k+1) for k in range(3,8))
self.d = DictDiffer(self.current, self.past)
def testAdded(self):
self.assertEqual(self.d.added(), set((5,6,7)))
def testRemoved(self):
self.assertEqual(self.d.removed(), set((0,1,2)))
def testChanged(self):
self.assertEqual(self.d.changed(), set((3,4)))
def testUnchanged(self):
self.assertEqual(self.d.unchanged(), set())
unittest.main()
def combine_two_json(json_request, json_request2):
intersect = {}
for item in json_request.keys():
if item in json_request2.keys():
intersect[item]=json_request2.get(item)
return intersect