Python search dictionary keys for search input
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.
Aristides
Updated on July 17, 2022Comments
-
Aristides almost 2 years
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?