Python skipping some lines in for loop - python

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.

Related

Displaying the first name alphabetically and last name alphabetically after being given a list of names from the user in python

Design a program that asks the user for a series of names (in no particular order). After the final person's name has been entered, the program should display the name that is first alphabetically and the name that is last alphabetically. For example, if the user enters the names Kristin, Joel, Adam, Beth, Zeb, and Chris, the program would display Adam and Zeb.
Note: A condition-controlled loop must be used. The user will enter a sentinel value of DONE to indicate that there are no more names to be input.
We really haven't gone over this in class and I've tried looking it up online to see if I can understand anything but most of the people are asking about it in java or C++.
My Code:
# Prompt user to enter names
names = input("Enter the names: ")
# breakdown the names into a list
words = names.split()
# sort the names
words.sort()
# display the sorted names
print("The sorted names are:")
for word in words:
print(word)
Best way to learn is to try it yourself. Most import things is (imho) to read the assignment carefully and then break it down in smaller, but easier to solve problems:
# init names list
names = []
# get input
while True:
name = input("Enter a name:")
# end while loop, when name = 'DONE'
if name == "DONE":
break;
else:
# else add it to 'names' list
names.append(name)
# Do some sorting of the list
names.sort()
# Print the first item of a list
print(names[0])
# Print the last item of a list
print(names[-1])
Here is a code that will solve your problem:
print("Keep entering names by typing space bar after every name. Once done, press Enter")
final_list = list(map(str, input().rstrip().split()))
final_list.sort()
print("The first name is {}. The last name is {}".format(final_list[0],final_list[-1]))

making a function to retrieve information from a key in a dictionary

I am a newbie programmer so sorry if any of these are dumb questions. This class is my first ever programming experience.
I am trying to create a search function that will search a dictionary and upon invoking it would give you all the keys from the dictionary separated by a '/t'. I then want to make the function prompt the user to enter a key. When the key is in the dictionary the key is supposed to give you the the information from the dictionary. When the key is not in the dictionary I want to create an output message such as "That student is not in class".
I have created a function off of my dictionary which will simply print all the information from the dict if you enter the correct key; however it is not off of the search function. I know I am lacking in having a true/except block that works, and a while true and return function.
I need to make (searchStudentDict) or use a true/except block or while true or a return statement. Below is my incorrect code trying to do this problem within it's boundaries.
def searchStudentDict():
for i in dctStudents.keys():
try:
while true:
except:
print('That student is not in class')
return
searchStudentDict(dctStudents)
I would be forever grateful to anyone who could edit this and get this to actually show up in the code block I've spent more time formatting than on my question. It isn't taking any of the indents i made
The expected output is the keys below tab separated such as
7373'\t'8274'\t'9651'\t'2213'\t'8787'\t'9999
*using python create tab here since the physical tab key will not tab them apart.
dctStudents = {
'7373':['Walter White',52,'Teacher'],
'8274':['Skyler White',49,'Author'],
'9651':['Jesse Pinkman',27,'Student'],
'2213':['Saul Goodman',43,'Lawyer'],
'6666':['Gus Fring',54,'Chicken Guy'],
'8787':['Kim Wexler',36,'Lawyer'],
'9999':['Tuco Salamanca',53,'Drug Lord'] }
One possible solution that may work for you:
#First print all the keys separated by tabs
print('\t'.join(someDict.keys()))
#Infinite loop
while True:
#read user input
userinput = input("Enter a key: ")
#the method get will try to get the key, if no matches will display the string passed.
print(someDict.get(userinput, "No key matches the dict"))
You can use * unpacking with sep argument of print:
print(*dctStudents, sep='\t')
When inside a function, this looks like:
def searchStudentDict():
print(*dctStudents, sep='\t')
...will print keys of the dictionary separated by tab space.
You can do following to retrieve value of a key if its present or throw a message if it's not present:
def searchStudentDict():
print(dctStudents.get(input('Enter key: '), 'That student is not in class'))
Something like this will display all of the keys from the dictionary separated by tabs
print('\t'.join(someDict.keys()))
If you want to search the dictionary for a specific key and print out the value that corresponds to that key while guarding against exceptions, the basic example is one way of doing so:
def searchStudentDict(someDict):
targetKey = ""
# End at user's request
while True:
targetKey = input("Enter a student ID (\'q\' to quit): ")
if targetKey.lower() == 'q':
break
# Search for it in dictionary using try-except (handle exceptions)
try:
print("Student {} Info: {}".format(targetKey, someDict[targetKey]))
except KeyError:
print("No information exists for this student")
except:
print("Some unknown error occurred")
# Handle how you see fit
print('Ending search...')
def main():
studentDict = {
'7373' : ['Walter White',52,'Teacher'],
'8274' : ['Skyler White',49,'Author'],
'9651' : ['Jesse Pinkman',27,'Student'],
'2213' : ['Saul Goodman',43,'Lawyer'],
'6666' : ['Gus Fring',54,'Chicken Guy'],
'8787' : ['Kim Wexler',36,'Lawyer'],
'9999' : ['Tuco Salamanca',53,'Drug Lord']
}
# Print the existing students
print('\t'.join(studentDict.keys()))
# Perform search
searchStudentDict(studentDict)
if __name__ == "__main__":
main()
And the corresponding output would be:
$ py -3 search.py
7373 8274 9651 2213 6666 8787 9999
Enter a student ID ('q' to quit): 8274
Student 8274 Info: ['Skyler White', 49, 'Author']
Enter a student ID ('q' to quit): 9999
Student 9999 Info: ['Tuco Salamanca', 53, 'Drug Lord']
Enter a student ID ('q' to quit): 1111
No information exists for this student
Enter a student ID ('q' to quit): q
Ending search...
Typically, you would not want to handle a search inside a dictionary this way (using try-except). A simple if statement or the use of get should suffice but if you require the use of a try-except, you would need to guard against the KeyError that would be raised if you try to access a key that does not exist. Hope this helps.

python, loops: searching against a list to see if item is present, appending to new list

I am trying to make a program where my students will enter their ID numbers so I can (later in the code) automate sending attendance, and record who has handed in homework and who hasn't so emails can be sent to parents. I have everything else made, but I cannot get the inputting of student ID's working.
What I am trying to do:
1)make sure that their input is 7 characters long
2)check their ID exists in 'fakeID'
2a)have the students confirm their name from 'classNames' with a y/n.
2b) append their name into inputIDList
3) if the input is == to 9999990 exit the loop.
What it is doing:
1) asking for input
2) moving on in the code and not looping
3) not appending inputIDList
I think I am making this too complicated for my current skill level.
edit:
The loop is not checking to see if the inputed ID is in my fakeID list.
Also, it isnt looping for, so once the input is entered it continues on with the next set of code.
edit2:
updated code that works. :D
fakeID = ['1111111','1111112','1111113','1111114','1111115']
classNames = ['name1', 'name2', 'name3', 'name4', 'name5']
toplist = list(zip(fakeID, classNames))
inputIDList =[]
def inputID():
while True:
id = input('Please enter your student ID and hit Enter')
if id == '9999990':
print('Done')
break
if id in fakeID:
inputIDList.append(id)
print('recorder')
continue
if id not in fakeID:
print('I do not know this ID. Please try again.')
continue
If I understood your problem correctly then I suppose that you are trying to save the ID numbers of the students in inputIdList and then check whether a particular ID is in inputIdList or not. In the last if condition you are trying to compare a List type object with a String type object which will definitely throw an TypeError. Instead define the following function and call it in the if condition.
def check_list(id):
try:
inputIdList.index(id)
return True
except TypeError:
return False
list.index() method tries to find the element in the list and returns the index number of the element. And then call this function in your if condition.
if check_list('9999990'):
print('done')
#break
Furthermore there is no need to assign inputIdList = [""] if you have already intialized it to inputIdList = [].
If the problem persists please send the output in the thread.
Here is something to get you started:
fakeID = {'1111111','1111112','1111113','1111114','1111115'}
while True:
id = input('Please enter your student ID and hit Enter')
if id == '9999990':
print('Done')
break
if id not in fakeID:
print('I do not know this ID. Please try again.')
continue
as Abarnert said you need to restructure your method. but I think I found where you were stuck.
after you have checked for the length of input number, you should check whether that number matches any fakeID,and get the corresponding class name.
so your first loop should be like this
for i in toplist:
rather than
for i in [i for i,x in enumerate(inputIDList) if x == fakeID]:
since inputIDList is empty your program will not go inside the loop. And inside the changed loop you should be checking
if s == fakeID
This is the limit of what I could understand of your desired operation. But if you need further help just ask.
cheers.

Is it possible to find out which condition is being met in a multi condition if then statement?

I'm working on a python/beautifulsoup web scraper. I'm searching for certain keywords, my statement looks like this:
if 'tribe' in entry or 'ai1ec' in entry or 'tfly' in entry:
print('Plugin Found!')
rating = easy
sheet.cell(row=i, column=12).value = rating
What I would like to do is find out which one of those keywords is making the statement true. My first instinct would be to write a nested loop to check but I wasn't sure if there was a way to capture the value that makes the statement true that would involve less code?
I would use a generator comprehension that I would pass to next with a default value. If the comprehension doesn't find anything, next returns the default value, else it returns the first found and stops there (kind of any, but which stores the result)
cases = ['tribe','allec','tfly']
entry = 'iiii allec rrrr'
p = next((x for x in cases if x in entry),None)
if p is not None:
print('Plugin Found!',p)
[EDIT: changed to only find first name]
for name in ('tribe', 'ailec', 'tfly'):
if name in entry:
print ('Name =', name)
print('Plugin Found!')
rating = easy
sheet.cell(row=i, column=12).value = rating
break

Searching for an equal string?

I am not sure how to word the question title.
a = "Alpha";
b = "Bravo";
c = "Charlie";
fn = input("What is your first name: ")
for fletter in fn.split():
fl = fletter[0]
The code above gets the first letter entered. The goal is to then get the first letter to possible check in a while loop to see if the value of fl = one of the starting strings. Is that possible to do? Tips on where to begin?
Solution 1 [Using a dictionary]
Also makes things much simpler.
In this case, instead of defining separate variables for each string, you store them in a dictionary. So for example, instead of this:
a = "Alpha"
b = "Bravo"
c = "Charlie"
You would have this:
letterwords = {"a":"Alpha", "b":"Bravo", "c":"Charlie"}
This works very similarly to a list, however instead of indexing the dictionary you would reference to separate objects inside a dictionary according to its key. So if the dictionary letterwords is defined as above, you would reference to the string Alpha by calling letterwords["a"]. Therefore, in this case, the code would look something like this:
letterwords = {"a":"Alpha", "b":"Bravo", "c":"Charlie"}
fn = input("Please enter your first name: ")
try:
letterwords[fn[0]]
except KeyError:
print("There is no matching variable with that letter in the database.")
Solution 2 [Using the eval() function]
Not recommended.
This is perfectly possible, with the eval function. However, you should be aware that this is a quite dangerous function to run, as malicious users can use this to control the console. (Especially if you imported os.) However, it should get you over the hump for now. Here's the code:
a = "Alpha"
b = "Bravo"
c = "Charlie"
fl = input("Please enter your first name: ")
try:
compared = eval(fl[0])
except NameError:
print("Your first name's first letter does not match any strings in the database.")
More information on the eval() function here: https://docs.python.org/3/library/functions.html#eval
Hope this helped!

Categories

Resources