Creating a lookup function - python

I want to create a python lookup function for students. I have a tab delimited file with ID and students name. I want to create a lookup program such that entering either a student's name or ID will return name of the student and student ID if a match has been found.
So far I have imported the data successfully. Snippet of data is shared. Having trouble defining a function. I am sharing my code below:
infile = open("D:/work/student_id.txt", "r")
def lookup():
word =raw_input("code to lookup: ")
print ("\n")
n = elements.index(word)
x = elements[n][0]
y = elements[n][0]
if word == x:
print x, ":", y, "\n"
else:
print("That code does not exist")
lookup()
I searched online(stackoverflow-found post by Erik and Alexander, I tried to model my code like theirs but still no help; O'riley books on Python) for help regarding creation of lookup function but they all involved writing the data out. But I found no guidance on creating a lookup function for an imported tab delimited file. I hope this will help others as well. Any advice?

What version of Python are you using?
Python 3 uses input(), not raw_input().
As your file is tab-separated you can use the csv function.
import csv
students = {}
search = input()
found = None
with open('student_id.txt', newline='') as csvfile:
reader = csv.reader(csvfile, delimiter='\t')
for row in reader:
students[row[0]] = row[1]
print(students)
for i in students.keys():
if search == i:
found = search + " " + students[i]
else:
if search == students[i]:
found = i + " " + students[i]
if found == None:
print("Not found")
else:
print(found)

Related

How to put the names in the code from .txt document for it to read

This code is trying to open a txt document read the names print them then ask to input a name and search for the name but the search doesn't work with text only with set names if anyone can help. I think its using data a a search request so don't know how to make the names it
def liner_search():
with open ("example.txt", "r") as myfile:
data = myfile.read().splitlines()
print (data)
numberList = [data]
searchRequest = input("enter name:")
print(searchRequest)
found = False
i=0
while found == False and i != len(numberList):
if numberList[i] == searchRequest:
print ("found")
found = True
else:
print("next")
i = i+1
liner_search()
this is the result
I propose a more pythonic approach:
def name_finder():
with open('example.txt', 'r') as my_file:
data = my_file.read().splitlines()
name = input("enter name:")
if name in data:
print("Name is in the list")
else:
print("Name is not in the list")
name_finder()

Creating a function to process through a .txt file of student grades

Can someone help...
My driver file is here:
from functions import process_marks
def main():
try:
f = open(argv[1])
except FileNotFoundError:
print("\nFile ", argv[1], "is not available")
exit()
process_marks(f)
f.close()
main()
I'm trying to modify process_marks(f) to run my code. and produce this (from file that runs without functions):
Names of students who have written tests:
Anthony Austyn Bronson Conor Mark
Enter name of student whose test results you wish to see: Anthony
Summary of Test Results for Anthony
===================================
Test scores: 85 85 85 85
Number of tests written .................. 4
This is what I currently have:
names = []
name_print = "\nSummary of Test Results for "
def process_marks(file_name):
names
for line in file_name:
names.append(line.split()[0])
print('\nNames of students who have written tests:')
print(*sorted(names), sep=' ')
name = input('Enter name of student whose test results '
'you wish to see: ')
check_name(name)
parts = line.split()
if parts[0] == name:
print_scores(name)
def check_name(person):
if person not in names:
print('\nNo test data found for ', person)
input("Press Enter to continue ...")
else:
print(name_print + person)
def print_scores(person, parts):
print('=' * ((len(name_print)) - 1))
test_scores = ' '.join(parts[1:])
print('Test scores: ', end=' ')
print(test_scores)
Which outputs:
Names of students who have written tests:
Anthony Austyn Bronson Conor Mark
Enter name of student whose test results you wish to see: Anthony
Summary of Test Results for Anthony
I need help making print_scores() function work in process_marks().
Can someone see where my errors lie?
Your error (mainly) lies in the fact that you are comparing the input name to the last row of the file. This is because you check if parts[0] == name where parts = line.split(). This means the parts are of the last row of the file always - no matter what name provided.
To fix this, I would start by a better way of storing your data. Right now you are just saving the names in a list. But what about the grades? I think a better solution would be to use a dict. So start by changing to:
names = {} # instead of []
Now you want to fill that dict with the names as keys (keeps the logic similar as with the list) and the list of grades as the value for that key. So your file parsing can look like:
for line in file_name:
elements = line.split()
names[elements[0]] = elements[1:]
# names now look like: {'Anthony': ['85', '85', '85', '85'], 'Conor': [...], ... }
Now another thing is that you call the check_name function but then make another check in process_marks. This seems redundant. I would change the ceck_name function to return a boolean indicating if the name is ok or not:
def check_name(person):
if person not in names:
print('\nNo test data found for ', person)
input("Press Enter to continue ...")
return False
else:
print(name_print + person)
return True
And in process_marks you can use it as:
name = input('Enter name of student whose test results you wish to see: ')
if check_name(name):
print_scores(name)
Lastly, regarding the parts issue. Now you have the grades stored in names along with the matching name they belong to. So all we have left to do is change print_scores to take only one argument grades and use that instead of parts, and from process_marks just call it:
print_scores(names[name])
A view of a possible complete code:
names = {}
name_print = "\nSummary of Test Results for "
def process_marks(file_name):
with open(file_name) as f:
for line in f:
elements = line.split()
names[elements[0]] = elements[1:]
print(names)
print('\nNames of students who have written tests:')
print(*sorted(names), sep=' ')
name = input('Enter name of student whose test results you wish to see: ')
if check_name(name):
print_scores(names[name])
def check_name(person):
if person not in names:
print('\nNo test data found for ', person)
input("Press Enter to continue ...")
return False
else:
print(name_print + person)
return True
def print_scores(grades):
print('=' * (len(name_print) - 1))
test_scores = ' '.join(grades)
print('Test scores: ', end=' ')
print(test_scores)

Loop through a text file with an input

I have a text file set out in this layout:
Greg,Computer Science,Hard,5
Alex,Computer Science,Medium,2
Fiona,Maths,Easy,0
Cassie,Maths,Medium,5
Alex,Maths,Medium,1
In my program I want the user to be able to choose a certain name and see their results. My code for this looks like this:
name = input("Enter name: ")
for each in file:
each = each.split(",")
realName = each[0]
subject = each[1]
difficulty = each[2]
score = each[3]
if name == realName:
print(subject, difficulty, score)
break
else:
print()
print("Invalid name.")
name = input("Re-enter your name: ")
A few things are wrong with it though and I can't figure out what to do:
If the user entered "Alex", only one of his results will be displayed.
If a wrong name is inputted once, every other name inputted will return as "Invalid".
If the correct name is inputted and the results are displayed, the program will continue to ask for a name.
Does anybody have any solutions to these problems?
If you're going to query your file repeatedly, I'd recommend pre-loading your data once into a dictionary, and printing data as and when needed. Something like this:
data = {}
with open('file.txt', 'r') as file:
for line in file:
realName, subject, difficulty, score = each.split(',')
data.setdefault(realName, []).append((subject, difficulty, score))
while True:
name = input('>>> ')
data.get(name, 'Invalid Name')
This solves problems one and two. If you just want to break after the first valid name is input, you can query the return value of dict.get:
while True:
name = input('>>> ')
result = data.get(name)
if result:
print(result)
break
print('Invalid name')
This solves problem three.
You're better off using the csv module since your file syntax is simple CSV.
Then you can loop through the rows (each row will be an array of values).
import csv
def parse_csv_file(csv_file, operation, value, index):
with open(csv_file, newline='') as file:
reader = csv.reader(file, delimiter=',',
quotechar='|')
return operation(reader,
value, index)
def find_first_row(csv_reader, value, index):
for row in csv_reader:
if row[index] == value:
return row
return None
def main():
query = input('Enter a name: ')
result = parse_csv_file('file.csv',
find_first_row,
query, 0)
if result:
print(result)
else:
print('Nothing found!')
main()

Trying to load and edit a pickled dictionary, getting an EOFError

I'm trying to modify a trivia program found in a book as part of a tutorial; I need to save the name and score of the player using a pickled dictionary. I've already created the dat file using a separate program, to avoid reading from a file that doesn't exist.
This is the code for the trivia program.
#Trivia Challenge
#Trivia game that reads a plain text file
import sys
def open_file(file_name, mode):
"""Open a file"""
try:
the_file = open(file_name, mode)
except IOError as e:
print("Unable to open the file", file_name, "Ending program.\n", e)
input("\n\nPress the enter key to exit.")
sys.exit()
else:
return the_file
def next_line(the_file):
"""Return next line from the trivia file, formatted."""
line = the_file.readline()
line = line.replace("/", "\n")
return line
def next_block(the_file):
"""Return the next block of data from the triva file."""
category = next_line(the_file)
question = next_line(the_file)
answers = []
for i in range(4):
answers.append(next_line(the_file))
correct = next_line(the_file)
if correct:
correct = correct[0]
explanation = next_line(the_file)
value = next_line(the_file)
return category, question, answers, correct, explanation, value
def welcome(title):
"""Welcome the player and get his or her name."""
print("\t\tWelcome to Trivia Challenge!\n")
print("\t\t", title, "\n")
def saving(player_name):
import pickle
f = open("trivia_scores.dat", "rb+")
highscores = pickle.load(f)
if player_name in highscores and score > highscores[player_name]:
highscores[player_name] = score
pickle.dump(highscores, f)
elif player_name not in highscores:
highscores[player_name] = score
pickle.dump(highscores, f)
print("The current high scores are as follows:")
print(highscores)
f.close()
def main():
trivia_file = open_file("trivia.txt", "r")
title = next_line(trivia_file)
welcome(title)
score = 0
#Get the first block
category, question, answers, correct, explanation, value = next_block(trivia_file)
while category:
#Ask a question
print(category)
print(question)
for i in range(4):
print("\t", i + 1, "-", answers[i])
#Get answer
answer = input("What is your answer?: ")
#Check answer
if answer == correct:
print("\nRight!", end=" ")
score += int(value)
else:
print("\nWrong!", end=" ")
print(explanation)
print("Score:", score, "\n\n")
#Get the next block
category, question, answers, correct, explanation, value = next_block(trivia_file)
trivia_file.close()
print("That was the last question!")
print("Your final score is", score)
return score
player_name = input("First, enter your name: ")
main()
saving(player_name)
input("\n\nPress the enter key to exit.")
The eponymous error occurs at this point:
def saving(player_name):
import pickle
f = open("trivia_scores.dat", "rb+")
highscores = pickle.load(f)
When the questions end, the program attempts to run the "saving" module, which (In theory) opens the trivia_scores.dat file, loads the highscores dictionary, checks to see if the player's name is in the dictionary, and if their current score is higher than the one in the file, it overwrites it.
But for some reason, when the program attempts to load the highscores dictionary, instead I get this error message.
EOFError: Ran out of input
I have never seen this error before. From some cursory googling, I got the impression that it has something to do with the program trying to read from an empty file. But that made no sense to me, since I specifically created a dat file using a different program to prevent that from happening: trivia_scores.dat is NOT an empty file. I even read from it with Python Shell to make sure.
What does this error mean, and why won't Python load the dat file?
Context: The book I'm reading from is Python for the Absolute Beginner, by Michael Dawson. This program and the challenge I'm trying to complete come from chapter 7. The program was running fine before I added the saving module.
Probably the original trivia_scores.dat file you wrote got corrupt (maybe you didn't call close() on it?). You should try creating a new file and adding a pre-populated dictionary to this file. Then try reading from this new file.

How do I allow only the latest inputs to be saved - Python

How do I implement a simple code that will only save the student's latest 3 scores? If the test is repeated later, the old score should be replaced.
Thank you.
This is the code that asks the user the questions and saves the results in the txt. files.
import random
import math
import operator as op
correct_answers = 0
def test():
num1 = random.randint(1, 10)
num2 = random.randint(1, 10)
ops = {
'+': op.add,
'-': op.sub,
'*': op.mul,
}
keys = list(ops.keys())
rand_key = random.choice(keys)
operation = ops[rand_key]
correct_result = operation(num1, num2)
print ("What is {} {} {}?".format(num1, rand_key, num2))
user_answer= int(input("Your answer: "))
if user_answer != correct_result:
print ("Incorrect. The right answer is {}".format(correct_result))
return False
else:
print("Correct!")
return True
username = input("What is your name? ")
print("Hi {}! Welcome to the Arithmetic quiz...".format(username))
class_name = input("Are you in class 1, 2 or 3? ")
correct_answers = 0
num_questions = 10
for i in range(num_questions):
if test():
correct_answers +=1
print("{}: You got {}/{} questions correct.".format(
username,
correct_answers,
num_questions,
))
class_name = class_name + ".txt" #creates a txt file called the class that the user entered earlier on in the quiz.
file = open(class_name , 'a') #These few lines open and then write the username and the marks of the student into the txt file.
name = (username)
file.write(str(username + " : " ))
file.write(str(correct_answers))
file.write('\n') #This puts each different entry on a different line.
file.close() #This closes the file once the infrmation has been written.
A much better solution would be to store the data in a different format that made everything easy. For example, if you used a shelve database that mapped each username to a deque of answers, the whole thing would be this simple:
with shelve.open(class_name) as db:
answers = db.get(username, collections.deque(maxlen=3))
answers.append(correct_answers)
db[username] = answers
But if you can't change the data format, and you need to just append new lines to the end of a human-readable text file, then the only want to find out if there are already 3 answers is to read through every line in the file to see how many are already there. For example:
past_answers = []
with open(class_name) as f:
for i, line in enumerate(f):
# rsplit(…,1) instead of split so users who call
# themselves 'I Rock : 99999' can't cheat the system
name, answers = line.rsplit(' : ', 1)
if name == username:
past_answers.append(i)
And if there were 3 past answers, you have to rewrite the file, skipping line #i. This is the really fun part; text files aren't random-access-editable, so the best you can do is either read it all into memory and write it back out, or copy it all to a temporary file and move it over the original. Like this:
excess_answers = set(past_answers[:-2])
if excess_answers:
with open(class_name) as fin, tempfile.NamedTemporaryFile() as fout:
for i, line in enumerate(fin):
if i not in excess_answers:
fout.write(line)
os.replace(fout.name, fin)
That part is untested. And it requires Python 3.3+; if you have an earlier version and are on Mac or Linux you can just use os.rename instead of replace, but if you're on Windows… you need to do some research, because it's ugly and no fun.
And now, you can finally just append the new answer, as you're already doing.

Categories

Resources