I am trying to implement a solution where I call the displayPerson() that takes the user input for an id number and will print the information for the user. I should note that I'm downloading a csv file from the internet that contains data in this format:
id, name , birthday
1, Jack Sparrow, 09/20/2000
My goal is to get a number from the user which will look up and display the ID. I want the prompt to continue to show up and ask the user for a number until they enter a negative number or 0 to exit.
page = downloadData(args.url)
persons = processData(page)
prompt= int(raw_input(" Enter ID of person you would like to search for: "))
displayPerson(prompt, persons)
displayPerson(prompt, persons)
When I try to pass the raw input of a number 1-99 I get a Key Error, even though there are ids with that number. If I simply hard code displayPerson(10, persons) for example, the code will run but if I raw_input 10 I will get an error. Why?
Here is my displayPerson function:
def displayPerson(id, personDataDictionary):
"""
:param id:
:param personDataDictionary: Look at displayPerson in __name__ function. But I thought bday was pieces[2].
:return:
"""
print("id = {}, name = {}, birthday = {}".format(id, personDataDictionary[id][0],
personDataDictionary[id][1].strftime("%Y-%m-%d")))
As it is written I can call the function using the former code snippet (the first one you see up there) and the program will run fine if I enter an integer as one of the parameters manually but won't allow me to take a value from 1-99 without throwing a Key Error. How do I accomplish this?
Where is the dictionary that you are raising the Key Error on? Are the keys inputted as integers or strings? That could be one element you want to look into. I'm not 100% sure what you're asking for but if it's how to restrict the value of the var prompt to be between 1 and 99:
prompt = 0
while prompt < 1 or prompt > 99:
prompt = int(raw_input(" Enter ID (1 - 99) of person you would like to search for: "))
do_something_with_key(prompt)
By the time you exit this loop, the value of prompt will be what you are looking for (unless what you're looking for is a string).
On my view,i suggest you to do this.
Reason:why you throw a Key error because your dictionary did not have such key,so you should care about if you can get the value by key instead of setting range
def displayPerson(id, personDataDictionary):
"""
:param id:
:param personDataDictionary: Look at displayPerson in __name__ function. But I thought bday was pieces[2].
:return:
"""
per = personDataDictionary.get(id)
while not per:
prompt = int(raw_input(" Enter ID of person you would like to search for: "))
per = personDataDictionary.get(prompt)
print("id = {}, name = {}, birthday = {}".format(id, per[id][0],
per[id][1].strftime("%Y-%m-%d")))
Related
in this problem, i have file.txt that looks like
Tanzania:2948
Lesotho:2932
Comoros:2751
Nepal:2702
Yemen:2606
Zimbabwe:2434
Solomon Islands:2427
Benin:2276
Guinea:2247
Mali:2218
Kiribati:2185
Rwanda:2043
Afghanistan:1976
Chad:1945
Ethiopia:1903
Uganda:1868
Burkina Faso:1866
etc.
my current code looks like
def makeDicts():
incomeDict = dict()
countryDict = dict()
countryList =[]
gdpList = []
initialList = []
with open('lab8.txt','r') as f:
for line in f:
line= line.upper().strip().split(':')
countryList.append(line[0])
gdpList.append(line[1])
initial =line[0][0]
initialList.append(initial)
for i in range(len(countryList)):
incomeDict[countryList[i]] = gdpList[i]
if initialList[i] not in countryDict:
countryDict[initialList[i]] = set()
countryDict[initialList[i]].add( countryList[i])
return (incomeDict,countryDict)
userinp = input('Enter File Name: ')
incomeDict , countryDict = makeDicts()
while True:
x = input("Enter a Coutry name or letter or DONE to quit: ")
x = x.upper()
if x=='DONE':
exit()
I know the function is made correctly as it was made based on exact instructions but I need to make the lower program which I am having trouble with these are the tasks.
For this exercise, we will write a program that makes use of two dictionaries. The program
will be able to do two different functions:
If a country name is entered, the program should report the per capita gross domestic
product (GDP) of that country.
If a letter is entered, the program should report all the countries that it has in the
system that start with that letter.
Finally, the specifications ask us to prompt the user for either an initial which returns the set of countries that start with that initial, or a country name that returns the corresponding income, or the word “DONE” which exits the program. We can accomplish this using a while loop that will run until the user enters “DONE”. It will check if the user entered text is in any of the dictionaries and return the appropriate value at that key. Write this into a main() function, with the following suggestions:
First, to construct the dictionaries, write a line of code like incomeDict , countryDict = makeDicts()
Write a while loop and repeated prompt the user for input.
After converting the input to upper-case, you should test whether the user typed in a country name or an initial. These can both be accomplished by testing whether the user input is a key in one of the dictionaries. For instance, if the user input is in a variable called x, then ‘x in countryDict’ will test if the user typed in a letter that is the start of one or more country names.
If the user types in a letter, report all of the countries that start with that letter: These countries start with F: {'FINLAND', 'FIJI', 'FRANCE'}
If the user types in a country name, report the per capita GDP of that country: FINLAND has per capita GDP of 46344
If the user types in DONE, then quit the program.
For all other inputs, report an error and prompt again.
can you please help me finish this
I have tried the code that I wrote above but I do not know how to scan the dictionarys and produce the output based on the instructions.
I do not know what type of functions or opperators I can use?
After the if x=='DONE': line, you will want to say as:
if x == 'DONE':
exit()
elif len(x) == 1:
if x in countryDict:
print(f"These countries start with {x}: {countryDict[x]}")
else:
print(f"No contries start with {x}")
else:
if x in incomeDict:
print(f"{x} has per capita GDP of {incomeDict[x]}")
else:
print(f"Country {x} not registered")
As a side note, the too small indentation may make the code less readable (IMHO).
Clarification: The user needs to specify an ID from a displayed list of ID's, how can I simplify the process by numbering the ID's so that the user just has to specify a simple number instead of the whole ID
I have a list ID = ['ekjgnrg','lrkjnk','etc..'] that I need to interact with by inputting the ID later on. The issue is it's a little tedious to type it in. (Copy-pasting would solve this but it doesn't work on mobile due to the way the message with the list is displayed.)
How can I assign a number to each string in the list so that the user can enter '1' instead of 'ekjgnrg' for simplicity? The list gets longer and shorter occasionally, so how can I make it scale to the size of the list?
Not sure how you present to user, but, you can do something like:
ID = ['ekjgnrg', 'lrkjnk', 'etc..']
print('Choose one of:')
for n,item in enumerate(ID):
print(f'{n}: {item}')
n = int(input('Enter ID number: '))
print(f'You choose number "{n}" which is "{ID[n]}".')
This really needs error checking, like gracefully handling if someone enters invalid data like "foo" or "1000"...
Results in:
Choose one of:
0: ekjgnrg
1: lrkjnk
2: etc..
Enter ID number: 1
You choose number "1" which is "lrkjnk".
You can access the Nth item using my_list[n] (in your case my_list is ID).
I suggest you to read: Python - Access List Items - W3Schools to understand how to work with list or other data structure in Python.
is this what you mean? if not, please elaborate more.
ID = ['ekjgnrg','lrkjnk','etc..']
print(ID)
needed_id = int(input("What item do you want from the above list?"))
needed_id -= 1 # since lists start at 0.
print(ID[needed_id])
when run:
['ekjgnrg', 'lrkjnk', 'etc..']
What item do you want from the above list?1
ekjgnrg
I'm currently taking my first Python course, and have no background in CS. I'm working on a hypothetical program that incorporates small problems from our discussion topics and critical thinking assignments in order to practice using the code in a way that makes sense to me (I'm a publicist and photographer). At the moment, the program is a client database for a publicist to add client info, print a full client list, and calculate tax withholding.
I'm struggling to create an infinite nested dictionary that is populated through user input. I've searched online, but can't quite find a solution that meets my hypothetical requirements.
For the "ADD" branch of the program, I would like to be able to add new clients/info to the nested dictionary (client_info). The program asks the user a series of questions, such as client ID, band name, contract end date, pay, and management. I'm hoping to use some kind of loop so that the user can add a bunch of bands to the client_info dictionary, and the program will automatically update and create a new dictionary for each band within the client_info dictionary.
I first populated client_info with four bands and their info. Then I created empty dictionaries (with number assignments for each empty dictionary) and wrote individual code for each empty dictionary (10 total), but this meant I had a lot of code, and I couldn't figure out a way to recycle code to streamline the program.
I have also tried using initials for the bands instead of a number thinking that there might be an easy way to assign the client ID, but that failed miserably and I couldn't find a way to make the program run.
# Define dictionary for client information
client_info = {1: {'band' : 'colfax_speed_queen','email' : 'csq#colfaxspeedqueen.com', 'contract' : '20190808', 'pay' : int(800), 'mgmt' : 'MGI'},
2: {'band' : 'the_ghoulies', 'email' : 'tg#theghoulies.com', 'contract' : '20191031', 'pay' : int(250), 'mgmt' : 'DIY'},
3: {'band' : 'hail_satan', 'email' : 'hs#hailsatan.com', 'contract' : '20190606', 'pay' : int(700), 'mgmt' : 'APG'},
4: {'band' : 'plastic_daggers', 'email' : 'pd#plasticdaggers.com', 'contract' : '20190420', 'pay' : int(1000), 'mgmt' : 'DIY'}}
# Pretend to create infinite nested dictionary for client information, but ultimately fail
c = 4
while c <= 19:
c += 1
client_info[c] = {}
# General greeting
print("Welcome to the client database.")
# Directions to use database
main_menu = str("""You can:
PRINT your client list.
ADD a new client to the database.
Calculate your TAX withholding.""")
print(main_menu, "\nWhat would you like to do?")
access_client = input()
# Add client to database
elif access_client.lower() == 'add':
while access_client.lower() == 'add':
# Request user input for client id
print("\nWhat is the client id?")
# Update client id
c = int(input())
# Request user input for client_info[c]['band']
print("What is the name of the band?")
# Update client_info[c]['band']
client_info[c]['band'] = input()
# Request user input for client_info[c]['email']
print("What is " + client_info[c]['band'] + "\'s email address?")
# Update client_info[c]['email']
client_info[c]['email'] = input()
# Request user input for client_info[c]['contract']
print("When does " + client_info[c]['band'] + "\'s contract end?")
# Update client_info[c]['contract']
client_info[c]['contract'] = int(input())
# Request user input for client_info[c]['pay']
print("What is your payment from " + client_info[c]['band'] + "?")
# Update client_info[c]['pay']
client_info[c]['pay'] = int(input())
# Request user input for client_info[c]['mgmt']
print("Who is managing " + client_info[c]['band'] + "?")
# Update client_info[c]['mgmt']
client_info[c]['mgmt'] = input()
# Notify user that system has been updated with client information
print("\nThank you for adding " + client_info[c]['band'] + "\'s information to the client database. The database has been updated.")
print(client_info[c])
print(client_info)
# Ask user to add another client
print("\nType ADD to add another client. Hit any other key to return to the main menu.")
add_client = input()
if add_client.lower() != 'add':
break
print(main_menu)
The while c <= 19 loop sort of works the way I want it to, but if the user doesn't know the last client id number, they could accidentally overwrite a previous entry.
If you print the full dictionary, then any blank dictionaries through 20 will get printed as well. If I wanted to have the option to have 200 entries in my dictionary, it would be annoying to have all those blank dictionaries print out when I want to see the full client list.
Since I currently have 4 entries in the dictionary, I have to have c = 4 above the while c <= 19 loop. (We haven't gone over how to save the content of user input at the moment, but I'm assuming that this would be an issue once I know how to save.) I would need to update the c = # every time I used the program. And if I use c = 0, it deletes the entries I've already saved in the dictionary.
I think I'm close, but it isn't as efficient as I would like it to be. I would appreciate any help you could give me as I'm a total noob and have no idea what I'm doing!
Thanks!
Rather than pre-populating your top level dictionary with empty inner dictionaries for clients you haven't entered yet, you should instead create each dictionary as you need it, just before you collect the information about the new client.
Your program can calculate the new client ID number automatically, using something like len(client_info) or len(client_info) + 1 to get a new number based on how many records you already have. Here's a very brief example of this, with a much simplified client record:
client_info = {} # start empty
while True:
new_client = {}
name = input("what is the band's name? ")
new_client['name'] = name
new_client_id = len(client_info) # starts at zero, add 1 if you want the IDs to start at 1
client_info[new_client_id] = new_client
print("client added, client_info is now", client_info)
You might also consider using a list for the top level of the data structure, if you never remove clients from it. Instead of generating an ID and indexing with it to assign the new client record, you'd just append the record to the list of clients. The ID would be implicit, as the position the client ended up in the list.
You could consider to do something like the raw example here below:
ids = client_info.keys()
next_c = max(ids) + 1
fields = ['band', 'email', 'contract', 'pay', 'mgmt']
for field in fields:
print("Enter ", field)
client_info[next_c][field] = input()
The basic idea is to find the next c to use as id looking for the max actual id + 1.
This allow to avoid to use already used ids, but not if last was deleted. To avoid reusing the already used id instead of deleting the object, set it to None (for eample):
client_info = {1: None, .....}
Declare the fields you need to populate in a list, so you can iterate over it ad keep code DRY.
This is just a starting point for further customisations.
For example, customising the answers:
fields_2 = {'band': 'What is the name of the band?', 'email': 'What is the band email address?', 'contract':'When does contract ends?', 'pay':'What is your payment from the band?', 'mgmt':'Who is managing the band'}
for field, answer in fields_2.items():
print(answer)
# client_info[next_c][field] = input()
So, the user could see:
# What is the name of the band?
# What is the band email address?
# When does contract ends?
# What is your payment from the band?
# Who is managing the band?
I have a python program where it prompts a user input for position or index and deletes the element in the list based on the position or index. The python program works but I'm having issues with the condition where if no user input is given, it automatically deletes the whole line in the list.
Example:
lst = [1,2,3,4,5]
enter position: 2
output: [1,2,4,5]
enter position: #user just pressed enter without giving any input
output: []
I'm writing the function within a class whereby:
def delete(self,index):
"""
This function deletes an item based on the index
:param self: the array
:param index: the index of an item in the array
:return: the array is updated
:raises: IndexError if out of range
"""
if not index:
self.__init__()
if index<0:
index = index + self.count
for i in range(index, self.count -1):
self._array[i] = self._array[i+1]
self.count-=1
and prompting the user input is as such:
position = int(input("Enter position:"))
it's not possible to just press 'enter' without receiving an error due to the position only receiving integers hence I'm looking for a method where if the user doesn't give any position, it registers it and prints just an empty list instead of an error message.
What you're looking for is the try-except block. See the following for an example:
input_invalid = true
while input_invalid:
user_input = input("Enter position: ")
try:
user_input = int(user_input)
input_invalid = false
except ValueError:
print("Please enter a valid integer!")
Here, the try-except block catches any errors (of the type specified
in except) thrown within the code block. In this case, the error results from trying to call int() on a string that does not contain an integer (ValueError). You can use this to explicitly prevent the error and control the logic flow of your program like shown above.
An alternate solution without using try-except is to use the .isdigit() method to validate the data beforehand. If you were to use .isdigit() (which I personally think is better), your code would look something like this:
input_invalid = true
while input_invalid:
user_input = input("Enter position: ")
if user_input.isdigit():
input_invalid = false
else:
print("Please enter a valid integer!")
Hope this helped!
I am very new to Python (started 2 days ago). I was trying to validate positive integers. The code does validate the numbers but it asks twice after a wrong input is entered. For example if I enter the word Python, it says: This is not an integer! like is supposed to but if I enter 20 afterwards, it also says it is not an integer and if I enter 20 again it reads it.
def is_positive_integer(input):
#error: when a non-integer is input and then an integer is input it takes two tries to read the integer
flag = 0
while flag != 1:
try:
input = int(input)
if input <= 0:
print "This is not a positive integer!"
input = raw_input("Enter the number again:")
except ValueError:
print "This is not an integer!"
input = raw_input("Enter the number again: ")
if isinstance(input, int):
flag = 1
return input
number = raw_input("Enter the number to be expanded: ")
is_positive_integer(number)
number = int(is_positive_integer(number))
Any help is appreciated.
The main bug is that you call is_positive_integer(number) twice with the same input (the first thing you enter).
The first time you call is_positive_integer(number), you throw away the return value. Only the second time do you assign the result to number.
You can "fix" your program by removing the line with just is_positive_integer(number) on its own.
However, your code is a little messy, and the name is_positive_integer does not describe what the function actually does.
I would refactor a little like this:
def input_positive_integer(prompt):
input = raw_input(prompt)
while True:
try:
input = int(input)
if input <= 0:
print "This is not a positive integer!"
else:
return input
except ValueError:
print "This is not an integer!"
input = raw_input("Enter the number again: ")
number = input_positive_integer("Enter the number to be expanded: ")
The problem stems from the fact that you're calling is_positive_integer twice. So, the first time it's called, you send it a string like 'hello', then it says it's not an integer and tells you to try again. Then you enter '20', which parses fine, and it's returned.
But then you don't save a reference to that, so it goes nowhere.
Then you call the function again, this time saving a reference to it, and it first tries the original bad string, which was still there in number. Then it complains that it's a bad input, asks you for a new one, and you provide it, terminating the program.