As stated in a previous (but different) question, I'm trying to figure out a 'simple' dictionary/database with Python, which will retrieve a name from a list of ten, with the requested information. i.e. input could be 'John phone', where the output is 'John's phone number is 0401' (which I have down pat); but I could also input 'John Birthday' or 'John hobbies' and the output would correspond.
As I'm a complete noob, I'm not even sure where to start. Several hours of googling and poring over lecture notes have yielded nothing so far.
I've got the feeling it's got something to do with the multiple argument % function but our lecturer really wasn't clear about how to take it further.
So far, what I have is:
#!/usr/bin/python
friends = {'John': {'phone' : '0401',
'birthday' : '31 July',
'address' : 'UK',
'interests' : ['a', 'b', 'c']},
'Harry': {'phone' : '0402',
'birthday' : '2 August',
'address' : 'Hungary',
'interests' : ['d', 'e', 'f']}}
name = raw_input ('Please enter search criteria: ')
if name in friends:
print "%s's phone number is: %s" % (name, friends[name]['phone'])
else:
print 'no data'
I'd also like to use the 'while' function so the prog doesn't close as soon as that information is given, but not sure if this would be appropriate.
Any pointers would be great, even if it's a 'try this' kind of hint, or a link to a relevant website.
Since this is homework, I'll limit my answer to some hints:
tok = name.split() would split name into a list of words, so 'John address' would become ['John', 'address'].
You can access the individual words as tok[0] and tok[1], and use them to index into friends to get the relevant person and then the relevant field.
I see no problem with wrapping the input/search logic into a while loop so that the user can perform multiple queries. The only thing to figure out is how you're going to exit that loop.
Based on your sample code, 'John phone' wouldn't work since it would actually be looking up 'John phone' as the name (and 'phone' is hardcoded). For illustration, try code like this:
response = raw_input('Please enter search criteria: ').split()
try:
print "%s's %s is %s" % (response[0], response[1], friends[response[0]][response[1]])
except KeyError:
print 'no data'
the split() takes each argument separately which can then be referenced with [0] and [1] (and so forth). You were already on the right track with % substitution, but this approach will give it more usability and readability.
The key is that you shouldn't need to check if the name matches (or the criteria matches). Assume it'll be there--and in the event of an exceptional case (that the matches aren't found), it can return 'no data' as expected.
Please enter search criteria: John phone
John's phone is 0401
Please enter search criteria: Harry birthday
Harry's birthday is 2 August
Listen to aix for the first part of your question. For the second part, I'd suggest coming up with an exit value (perhaps 'exit') that the user could type to leave the program, then have your while loop keep going while input is not that value.
Related
I am trying to build a python program to take a users input of the year of the car, and after that the model (no need for the make it will only contain fords). And with the year and model, the program will reference to the correct year and model and get the corresponding capacity information of the vehicle (engine oil, coolant, brake fluid etc.).
My question comes in with, how do I go about storing that information?
I was thinking to make a car_list dict and to the key years nest the first year 1998 inside that nest a list of the cars in that year, and in each car nest a dictionary of the specs.
car_list = {'years' : {1998 : [{'accord': {'oil' : '4.0 qts', 'coolant': '2 gals'} 'civic': {'oil': '4.5 qts', 'coolant': '3 gals'}]}
Will this work? Am I going about this wrong?
Simple program that may solve your problem (in python3):
model=input("model:")
year=input("year:")
query={model1:{year1:specs1,year2:specs2 ... }, model2:{ ... } ... }
print(query[model][year])
The specs could be either list or dictionary. It depends on how you want to use the data.
The program would prompt for user input and then print you the specs of the intended year and model as either a list or a dictionary. The output should be manipulated to fit your needs.
Using dictionary is a good idea here. But your code doesn't look right. Use this format:
car_list = {'1998' : {'accord': {'oil' : '4.0 qts', 'coolant': '2 gals'}, 'civic': {'oil': '4.5 qts', 'coolant': '3 gals'}}}
print(car_list['1998']['civic']['oil'])
You can store all the information in a nested dictionary, I think that's the best way. The dictionary can look like this:
car_list = {"1998":{"ka":["4.0 qts", "2 gals"],
"fiesta":["3.0 qts", "2.3 gals"]},
"2001":{"kuga":["3.3 qts", "3 gals"],
"mondeo":["4.0 qts", "3.5 gals"]}}
If you ask the user via input() for the year and car, you can print the information all by once if you use a for-loop:
input_year = input("Year?\n> ")
input_car = input("Car?\n> ")
for info in car_list[input_year][input_car]:
print(info)
or give them the information one by one:
input_year = input("Year?\n> ")
input_car = input("Car?\n> ")
i = car_list[input_year][input_car]
print("Oil: {}\nCoolant: {}".format(i[0], i[1]))
I've got a script I'm writing, and have a function that should search a dictionary with this layout:
{
1 : ['name1','name2','name3','name4','name5'],
2 : ['name1','name2','name3','name4','name5']
}
for a word. Here's the function:
def find_student(list_curr):
''' (str, dict) -> list
Input is the student's name and the dictionary of lists that they should exist in; output is a list in the format:
[group,index]
'''
while True:
try:
stu_name = input("\nPlease enter the first or last name of the student, or press enter to exit:\n> ")
if not stu_name:
return False
else:
break
except ValueError:
print("Please enter a valid name")
for g,s in list_curr.items():
print("G",g)
print("S",s)
if any(stu_name in n for n in s):
# name was in group
print("\nFound a possible match: {} (group {}):".format(s[s.index(stu_name)],g))
pp.pprint(s)
if input("\nIs this the student you're looking for?\n> ") in "yesYES":
# found the correct student
print("Saving {} for group and {} for index.".format(g,s.index(stu_name)))
stu_info = [g,s.index(stu_name)]
return stu_info
# nothing was found
print("\n{} was not found in the list.".format(stu_name))
return False
When I run it, though, it breaks as soon as it finds a match. Everything below the if any(): part is not run, and it just returns without even printing the Found a possible match... line. I've tried using the debugger in IDLE but it continually crashes whenever I open it. I've seen other posts really similar to this, but don't understand where I'm going wrong. Any ideas?
Edit: sorry, had for any(), should be if any().
You may be getting a ValueError on
if any(stu_name in n for n in s):
# name was in group
print("\nFound a possible match: {} (group {}):".format(s[s.index(stu_name)],g))
any(stu_name in n for n in s) checks if stu_name occurs as a substring of a string in list s.
The s.index(stu_name) however tries to find the index of an exact match between stu_name and the elements within s.
Try substituting example values to see what's going on:
s = ['James Joyce', 'Tom Stoppard', 'William Shakespeare']
stu_name = 'William'
print(any(stu_name in name for name in s))
print(s.index(stu_name))
Not sure why you're not seeing an Exception, perhaps there's a naked Except clause somewhere else in your code?
If the above issue is your problem, maybe write an inline function like this within find_student:
def get_index(stu_name, names):
for index, name in enumerate(names):
if stu_name in name:
return index
and call get_index(stu_name, s) instead of s.index(stu_names).
Alternatively, maybe you just want to edit your code so that you only accept exact matches.
In which case,
if any(stu_name in name for name in s):
becomes
if stu_name in s:
And the user needs to enter "William Shakespeare" instead of just "William".
P.S. This isn't what was asked for in the op, but...
What happens if there are multiple people with the inputted first/last name in the same group? As I see it, it looks like the script will only give the user the option to choose the index of the first match, and if the user says this isn't the student in question, the script starts looking at the next group, rather than returning the next index within the same group.
This question already has answers here:
Check if a given key already exists in a dictionary
(16 answers)
Closed 9 years ago.
I have created a dictionary in python as my first 'major' project. I'm using it to keep track of key words as I go along. The entered are just examples so feel free to improve my definitions (:
I'm new to python so feel free to criticise my technique so I can learn before it gets any worse!
What I'm wondering is, would there be a way to deal with searches that are not included in the dictionary.
As in 'Sorry, the word you were looking for could not be found, would you like to try another search?'
Anyway, here's my code:
Running = True
Guide = {
'PRINT': 'The function of the keyword print is to: Display the text / value of an object',
'MODULO': 'The function of Modulo is to divide by the given number and present the remainder.'
'\n The Modulo function uses the % symbol',
'DICTIONARY': 'The function of a Dictionary is to store a Key and its value'
'\n separated by a colon, within the {} brackets.'
'\n each item must be separated with a comma',
'FOR LOOP': 'The For Loop uses the format: \n '
'For (variable) in (list_name): (Do this)',
'LINE BREAKS': ' \ n ',
'LOWERCASE': 'To put a string in lower case, use the keyword lower()',
'UPPERCASE': 'To put a string in upper case use the keyword upper()',
'ADD TO A LIST': 'To add items to a list, use the keyword: .append'
'\n in the format: list_name.append(item)',
'LENGTH': 'To get the length of a STRING, or list use the keyword len() in the format: len(string name)', }
while Running:
Lookup = raw_input('What would you like to look up? Enter here: ')
Lookup = Lookup.upper()
print Guide[str(Lookup)]
again = raw_input('Would you like to make another search? ')
again = again.upper()
if again != ('YES' or 'Y'):
Running = False
else:
Running = True
You can use a try/except block:
try:
# Notice that I got rid of str(Lookup)
# raw_input always returns a string
print Guide[Lookup]
# KeyErrors are generated when you try to access a key in a dict that doesn't exist
except KeyError:
print 'Key not found.'
Also, in order for your code to work, you need to make this line of code:
if again != ('YES' or 'Y'):
like this:
if again not in ('YES', 'Y'):
This is because, as it currently stands, your code is being evaluated by Python like so:
if (again != 'YES') or 'Y':
Furthermore, since non-empty strings evaluate to True in Python, having the code like this will make the if-statement always return True because 'Y' is a non-empty string.
Finally, you can completely get rid of this part:
else:
Running = True
since it does nothing but assign a variable to what it already equals.
Two options.
Use the in operator:
d = {}
d['foo'] = 'bar'
'foo' in d
Out[66]: True
'baz' in d
Out[67]: False
Or use the get method of your dictionary and supply the optional default-to argument.
d.get('foo','OMG AN ERROR')
Out[68]: 'bar'
d.get('baz','OMG AN ERROR')
Out[69]: 'OMG AN ERROR'
You can get what you want if you replace
print Guide[str(Lookup)]
with
badword = 'Sorry, the word you were looking for could not be found, would you like to try another search?'
print Guide.get(lookup,badword)
One thing that jumped out is naming your dict with a capital letter. Generally capital letters are saved for classes. Another kind of funny thing is that this is the first time I've seen a dict actually used as a dictionary. :)
This is a homework question, I got the basics down, but I can't seem to find the correct method of searching two parallel arrays.
Original Question: Design a program that has two parallel arrays: a String array named people that is initialized with the names of seven people, and a String array named phoneNumbers that is initialized with your friends' phone numbers. The program should allow the user to enter a person's name (or part of a person's name). It should then search for that person in the people array. If the person is found, it should get that person's phone number from the phoneNumbers array and display it. If the person is not found, program should display a message indicating so.
My current code:
# create main
def main():
# take in name or part of persons name
person = raw_input("Who are you looking for? \n> ")
# convert string to all lowercase for easier searching
person = person.lower()
# run people search with the "person" as the parameters
peopleSearch(person)
# create module to search the people list
def peopleSearch(person):
# create list with the names of the people
people = ["john",
"tom",
"buddy",
"bob",
"sam",
"timmy",
"ames"]
# create list with the phone numbers, indexes are corresponding with the names
# people[0] is phoneNumbers[0] etc.
phoneNumbers = ["5503942",
"9543029",
"5438439",
"5403922",
"8764532",
"8659392",
"9203940"]
Now, my entire problem begins here. How do I conduct a search (or partial search) on a name, and return the index of the persons name in the people array and print the phone number accordingly?
Update: I added this to the bottom of the code in order to conduct the search.
lookup = dict(zip(people, phoneNumbers))
if person in lookup:
print "Name: ", person ," \nPhone:", lookup[person]
But this only works for full matches, I tried using this to get a partial match.
[x for x in enumerate(people) if person in x[1]]
But when I search it on 'tim' for example, it returns [(5, 'timmy')]. How do I get that index of 5 and apply it in print phoneNumbers[the index returned from the search]?
Update 2: Finally got it to work perfectly. Used this code:
# conduct a search for the person in the people list
search = [x for x in enumerate(people) if person in x[1]]
# for each person that matches the "search", print the name and phone
for index, person in search:
# print name and phone of each person that matches search
print "Name: ", person , "\nPhone: ", phoneNumbers[index]
# if there is nothing that matches the search
if not search:
# display message saying no matches
print "No matches."
Since this is homework, I'll refrain from giving the code outright.
You can create a dict that works as a lookup table with the name as the key and the phone number as its value.
Creating the lookup table:
You can easily convert the parallel arrays into a dict using dict() and zip(). Something along the lines of:
lookup = dict(zip(people, phoneNumbers))
To see how that works, have a look at this example:
>>> people = ["john", "jacob", "bob"]
>>> phoneNumbers = ["5503942", "8659392", "8659392"]
>>> zip(people, phoneNumbers)
[('john', '5503942'), ('jacob', '8659392'), ('bob', '8659392')]
>>> dict(zip(people, phoneNumbers))
{'jacob': '8659392', 'bob': '8659392', 'john': '5503942'}
Finding if a person exist:
You can quickly figure out if a person (key) exist in the lookup table using:
if name in lookup:
# ... phone number will be lookup[name]
List of people whose name matches substring:
This answer should put you on the right track.
And of course, if the search returns an empty list there are no matching names and you can display an appropriate message.
Alternative suggestion
Another approach is to search the list directly and obtain the index of matches which you can then use to retrieve the phone number.
I'll offer you this example and leave it up to you to expand it into a viable solution.
>>> people = ["john", "jacob", "bob", "jacklyn", "cojack", "samantha"]
>>> [x for x in enumerate(people) if "jac" in x[1]]
[(1, 'jacob'), (3, 'jacklyn'), (4, 'cojack')]
If you hit a snag along the way, share what you've done and we'll be glad to assist.
Good luck, and have fun.
Response to updated question
Note that I've provided two alternative solutions, one using a dict as a lookup table and another searching the list directly. Your updates indicate you're trying to mix both solutions together, which is not necessary.
If you need to search through all the names for substring matches, you might be better off with the second solution (searching the listdirectly). The code example I provided returns a list (since there may be more than one name that contain that substring), with each item being a tuple of (index, name). You'll need to iterate throught the list and extract the index and name. You can then use the index to retrieve the phone number.
To avoid just giving you the solution, here's related example:
>>> people = ["john", "jacob", "bob", "jacklyn", "cojack", "samantha"]
>>> matches = [x for x in enumerate(people) if "jac" in x[1]]
>>> for index, name in matches:
... print index, name
...
1 jacob
3 jacklyn
4 cojack
>>> matches = [x for x in enumerate(people) if "doesnotexist" in x[1]]
>>> if not matches:
... print "no matches"
...
no matches
You might want to look here for the answer to How do I ... return the index of the persons name in the people array.
I'm fairly new to python and for the life of me I can't get this to work. I want to set this little script to check to see if what the user types in is equal to any of the names on the list and if it is execute a function. If what the user types in isn't one of the names it should do a different function. This seems like it should be simple but I can't figure it out. I've gotten it to work with multiple elif statements to check for each case but it seems like there should be a more elegant solution then simply typing out 50 elif statements every time I want to check for a name.
Current script:
names=['Scott', 'Doug', 'Sam', 'Harry']
typedname=str(input('What is your name?: '))
if typedname==['Scott' or 'Doug' or 'Sam' or 'Harry']:
print('you are '+typedname)
else:
print('You are not in the names list')
if typedname in ['Scott', 'Doug', 'Sam', 'Harry']:
print('You are', typedname):
else:
print('You are not in the names list')
Python 3.2 brings an optmization for that cases:
if typedname in {'Scott', 'Doug', 'Sam', 'Harry'}:
will be translated to a frozenset and the search will be in constant time and the set will be built while compiling bytecode.
You can use the in keyword to check if typedname is in names:
if typedname in names:
# do whatcha do