So here's my question:
I want to search a dictionary to see if any key contains a user-inputted keyword. For example, the user searches for John.
elif option == 3:
count = 0
found = None
search_key = input("What do you want to search for? ").lower()
for key, val in telephone_directory.items(): #takes each element in telephone directory
if search_key in key: #checks if it contains search_key
if found is None:
found = val
count = 1
if found is not None:
print(" ")
print("More than one match found. Please be more specific.")
print(" ")
count = 2
break
if found is None:
print("Sorry, " + str(search_key) + " was not found.")
print(" ")
function_options() #redirects back
if found is not None and count < 2:
print(str(search_key) + " was found in the directory.")
print("Here is the file on " + str(search_key) + ":")
print(str(search_key) + ":" + " " + telephone_directory[search_key])
print(" ")
function_options() #redirects back
So this is where I am right now. Whatever the search may be, even if it is the entire key, it returns "was not found". What am I doing wrong?
You need to make a few choices; allow multiple matches, find only the first match, or only allow for at most one match.
To find the first match, use next():
match = next(val for key, val in telephone_directory.items() if search_key in key)
This will raise StopIteration if no match was found; return a default instead or catch the exception:
# Default to `None`
match = next((val for key, val in my_dict.items() if search_key in key), None)
try:
match = next(val for key, val in telephone_directory.items() if search_key in key)
except StopIteration:
print("Not found")
These versions will only loop over the dictionary items until a match is found, then stop; the full for loop equivalent would be:
for key, val in telephone_directory.items():
if search_key in key:
print("Found a match! {}".format(val))
break
else:
print("Nothing found")
Note the else block; it is only called when the for loop was allowed to complete, and was not interrupted by a break statement.
To find all matching keys, use can use a list comprehension:
matches = [val for key, val in telephone_directory.items() if search_key in key]
Finally, to allow for only one match, efficiently, use two next() calls on the same iterator, and raise an error if a second match is found:
def find_one_match(d, search_key):
d = iter(d.items())
try:
match = next(val for key, val in d if search_key in key)
except StopIteration:
raise ValueError('Not found')
if next((val for key, val in d if search_key in key), None) is not None:
raise ValueError('More than one match')
return match
Adapting that to the for loop approach again, would require you to break only if a second item is found:
found = None
for key, val in telephone_directory.items():
if search_key in key:
if found is None:
found = val
else:
print("Found more than one match, please be more specific")
break
else:
if found is None:
print("Nothing found, please search again")
else:
print("Match found! {}".format(found))
Your version doesn't work because you print 'not found' for each and every key that doesn't match. You can only know that you didn't match a key until the very end when you've iterated over all the keys in your dictionary.
Related
database = {}
while True:
print("Pleas type like Command,textA,textB")
Command, textA, textB = input().split(',')
if Command == 'PUT': // ex: PUT,a,c PUT is command to a is key, c is value
database[textA] = textB
print("Success!")
elif Command == 'GET': // ex: GET,a GET is command to get a's value
if "textA" in database:
print(database.get('textA'))
else:
print("Not exist!")
elif Command == 'DELETE': // ex: DELETE,a DELETE is command to delete a's key&value
if "textA" in database:
del database['textA']
print("Success!")
else:
print("Not exist!")
elif Command == 'LIST':
if "textA" in database:
for KEY, VALUE in database.items():
print(KEY, VALUE)
else:
print("Not exist!")
I would like to receive a command and key value in the dictionary and operate the if statement according to each command.
However, if statement works only when three values are received unconditionally, so GET, DELETE, and LIST cannot be used.
I'm trying to use TRY and EXCEPT, but I don't understand well.
Also, if you enter textA and textB exactly like that, I wonder if Key and Value will continue to be stored in the Dictionary Database.
There are many restrictions because the input format is Command, textA, and textB unconditionally.
I think I have to organize it with a repeat sentence, but I wonder if there is another way.
I think you are a python beginner, because some things went wrong in your code as i understand your intentions:
To comment Text use #, not //
To use a variable name them directly, do not use quotes, quotes are for strings
You should use lowercase variable names with underscores (PEP Styleguide)
To fix you problem of splitting, you can use a list to hold your data and than pop the items from list and use try catch block that catches only the IndexError
database = {}
while True:
print("Pleas type like Command,textA,textB")
in_data = input().split(',') # Save into list
Command = in_data.pop(0) # Take 1 element
textA = in_data.pop(0) # Take 1 element
try:
textB = in_data.pop(0) # Take 1 element ..
except IndexError: # .. if available
textB = None
if Command == 'PUT': # ex: PUT,a,c PUT is command to a is key, c is value
database[textA] = textB
print("Success!")
elif Command == 'GET': # ex: GET,a GET is command to get a's value
if textA in database:
print(database.get(textA))
else:
print("Not exist!")
elif Command == 'DELETE': # ex: DELETE,a DELETE is command to delete a's key&value
if textA in database:
del database[textA]
print("Success!")
else:
print("Not exist!")
elif Command == 'LIST':
if textA in database:
for KEY, VALUE in database.items():
print(KEY, VALUE)
else:
print("Not exist!")
Additonaly you should check your input (e.g. has it the correct type), to be more safe and you can define a default value for dict.get (print(database.get(textA, "Not exist!")))
You can pad the split text with extra empty strings so that the unpacking always works:
Command, textA, textB, *_ = input().split(',')+['','']
Try this:
from itertools import zip_longest
text = input().split(',')
Command, textA, textB = dict(zip_longest(range(3),text)).values()
or this:
from itertools import zip_longest
from types import SimpleNamespace
text = input().split(',')
params = SimpleNamespace(**dict(zip_longest(['Command', 'textA', 'textB'],text)))
# test
print(params.Command)
print(params.textA)
print(params.textB)
def SearchEntryComment():
print("\n\nSearch for guestbook comment with a keyword\n")
CommentSearch = input("Enter key word for search: ")
for i in range(len(dlGuestBook)):
if CommentSearch in dlGuestBook[i]["Comment"]:
print(i+1, ".", dlGuestBook[i] ["FirstName"], dlGuestBook[i]["LastName"], dlGuestBook[i]["Date"])
print(dlGuestBook[i]["Comment"], "\n")
else:
print("No results found")
print("\n")
This is my current code however when I run it for every element in the list it will print "no results found" and if it is there it will print that one. I want it to either print the results that are there or just no results found.
just using resultCount to save count of result found in list, and check the count after for loop.
def SearchEntryComment():
print("\n\nSearch for guestbook comment with a keyword\n")
CommentSearch = input("Enter key word for search: ")
resultCount = 0
for i in range(len(dlGuestBook)):
if CommentSearch in dlGuestBook[i]["Comment"]:
print(i+1, ".", dlGuestBook[i] ["FirstName"], dlGuestBook[i]["LastName"], dlGuestBook[i]["Date"])
print(dlGuestBook[i]["Comment"], "\n")
resultCount += 1
if resultCount == 0:
print("No results found")
print("\n")
Look closely at what your for loop is doing.
for i in range(len(dlGuestBook)): # for each entry in the guestbook
if CommentSearch in dlGuestBook[i]["Comment"]:
# print the comment
else:
print("No results found")
I think what you want is to only print "No results found" after your loop finishes, if it hasn't found any results. Something like this might be a solution.
foundComment = False
for i in range(len(dlGuestBook)):
if CommentSearch in dlGuestBook[i]["Comment"]:
foundComment = True
# print the comment
if not foundComment:
print("No results found")
I was wondering if someone could help me see what i am doing wrong with this search function for a binary search tree. Have to use the iterative version due to the size of data. I keep getting stuck in an infinite while loop when i print out values for debugging. Thanks!
I also get this error:
while (word_search.value != user_input) and (word_search.value != None):
AttributeError: 'NoneType' object has no attribute 'value'
def iterative_word_search(current, user_input):
word_search = current.root
print("User input value", user_input)
print("Word Search Value", word_search.value)
while (word_search.value != None) and (word_search.value != user_input):
print("While Loop value: ", word_search.value)
if(user_input < word_search.value):
word_search = word_search.left
# print("If statement value: " ,word_search.value)
elif(word_search.right != None):
word_search = word_search.right
print("Else statement value: ", word_search.value)
elif(word_search.value == None):
print("Word does not exist")
return word_search
return word_search
You need to assert that left and right are not None before calling .value on them:
Python lazy evaluation of expressions allows you to do this on one line. if word_search is None or word_search.value is None will evaluate word_search, and if it is None, will not evaluate word_search.value.
def iterative_word_search(current, user_input):
word_search = current.root
while True:
if word_search is None or word_search.value is None:
print("not found")
break
if word_search.value == user_input:
print("found")
break
if(user_input < word_search.value):
word_search = word_search.left
elif(word_search.right != None):
word_search = word_search.right
return word_search
Thank you for all the help!
Solved the problem. It dealt with user input and the files that i read in.
The files that i read in had a '\N' attached to it. Which is why i kept getting multiple errors and it was not searching the word.
So I have a code for my dictionary:
def get_rooms_for(dict1, num):
try:
for x in dict1:
if x == num:
print(dict1[x])
except KeyError:
print (num,"is not available.")
And my test is
get_rooms_for({'CS101':3004, 'CS102':4501, 'CS103':6755,'NT110':1244, 'CM241':1411}, 'CS999')
And I expect my result is to print out 'num' parameter with string saying
CS999 is not available.
But when I put it this it returns empty
What should i have to do if I want to pick an KeyError in dictionary, using exception code??
When you enter the try loop you're then looping over all the keys in the dictionary. CS999 isn't a key in the dictionary, so you never try to access it. Thus you never hit a KeyError, and the except clause is never reached.
What you want to do is more like this:
def get_rooms_for(dict1, num):
if num in dict1:
print(dict1[num])
else:
print("{} is not available".format(num))
But Python already has a method for that: get
dict1.get(num, "{} is not available".format(num))
Which will return the value mapped to num if it's in the dictionary, and "{} is not available".format(num) if it's not.
try this one :
def get_rooms_for(dict1, num):
try:
print(dict1[num])
except KeyError:
print (num,"is not available.")
Try this :
def get_rooms_for(dict1, num):
try:
for x in dict1:
if dict1[num] == x:
print "It will print particular key's {0} value if its exists or It will generate keyerror".format(dict1[num])
print(dict1[x])
except KeyError:
print (num,"is not available.")
Output :
('CS999', 'is not available.')
You also can try without try and exception :
def get_rooms_for(dict1, num):
if dict1.has_key(str(num)): # or str(num) in dict1
print "Key available"
else:
print num,"is not available."
get_rooms_for({'CS101':3004, 'CS102':4501, 'CS103':6755,'NT110':1244, 'CM241':1411}, 'CS999')
output:
CS999 is not available.
description=""" am id: asdm12
store : 231
mob : 00000000"""
if any("am id:" in line for line in dataList ):
amid_list= line.split(":")
newAccMap['AMID'] = amid_list[1]
popup(newAccMap['AMID'])
print "AM ID:",amid_list[1]
else:
print " NO AMID"
popup("No AMID")
so this is my code: I want "AM ID:" value , I have used description.splitlines() function and stored it in list . Now in that list I need to search for " AM ID:" if it is present I need get value connected to that colon . else print no am id .
You could use a for/else loop:
for line in description.splitlines():
key, val = line.split(":")
if key.strip() == "am id":
print(val.strip())
break
else:
print("no am id")
Here, the else part is executed only if the loop terminated normally, i.e. without hitting the break.