How to input 2 items in a record - python

I was wondering if there was a way to input 2 items into an array (2 dimensional) at least. One part of the array to hold the name of the person that was golfing, and the other part of the array to hold the score of the person that was playing.
scores = []
playerName = "Cynthia"
playerScore = "72"
scoreEntry = [playerName, playerScore]
The code above shows it being hard coded into it so the resulting would be [Cynthia, 72], but I am trying to figure out how to grab the input from the user and tried applying directly to the array, but it ends up coming out to this below.
How many players: 1
Enter a name: Cynthia
Enter a score: 72
Data written out is: C : y
Data written out is: 7 : 2
This is the output im currently getting
Code below for what I used to get this
def main():
golfFile = open ("golf.dat", 'w')
scores = []
SIZE = getSize()
playerName = getName(scores, SIZE)
playerScore = getScore(scores, SIZE)
scoreEntry = [playerName, playerScore]
scores.append(scoreEntry)
for scoreEntry in scores:
fileLine = scoreEntry [0] + " : " + str(scoreEntry [1]) + "\n"
golfFile.write (fileLine)
print("Data written out is: ", fileLine)
golfFile.close()
def getSize():
SIZE = int(input("How many players: "))
return SIZE
def getName(scores, SIZE):
index = 0
while (index <= SIZE - 1):
nameInput = input("Enter a name: ")
scores.append(nameInput)
index = index + 1
return scores
def getScore(scores, SIZE):
index = 0
while(index <= SIZE - 1):
scoreInput = input("Enter a score: ")
scores.append(scoreInput)
index = index + 1
return scores
main()
Expected output is
[Cynthia, 72]
There is an error that comes up as well
Traceback (most recent call last):
File "d:\Programs\test.py", line 35, in <module>
main()
File "d:\Programs\test.py", line 11, in main
fileLine = scoreEntry [0] + " : " + str(scoreEntry [1]) + "\n"
TypeError: can only concatenate list (not "str") to list
Also, I do not want to use any libraries at all for this

You're appending to scores in the getName() and getScore() functions, and each of them return the whole scores list. Then you're putting those two references to scores in the scoreEntry list, and then appending that list to scores again. So you've got the lists nested several levels deep, and you never have each name in the same list as the corresponding score.
Instead, you should just read one name and score each time through a single loop. Put those in a scoreEntry tuple, and append that to the scores list.
def main():
scores = []
SIZE = getSize()
for _ in range(SIZE):
playerName = getName()
playerScore = getScore()
scoreEntry = (playerName, playerScore)
scores.append(scoreEntry)
with open ("golf.dat", 'w') as golfFile:
for scoreEntry in scores:
fileLine = scoreEntry [0] + " : " + str(scoreEntry [1]) + "\n"
golfFile.write (fileLine)
print("Data written out is: ", fileLine)
def getSize():
SIZE = int(input("How many players: "))
return SIZE
def getName():
nameInput = input("Enter a name: ")
return nameInput
def getScore():
scoreInput = int(input("Enter a score: "))
return scoreInput
main()

Related

Why is my write to file function overriding my previous file text?

I'm trying to add user entered data to a tuple, then write that tuple on a line in my text file. I'm doing something wrong because only the last call is added to the txt file. Here's my functions:
def write_to_file(tuple1):
with open('student_info.txt', 'w') as f:
f.write(' '.join(x for x in tuple1))
f.write("\n")
def get_student_info(student_name):
tuple1 = ()
tuple1 = tuple1 + (student_name,)
print("\nScores for " + student_name)
print("Enter a test score (or enter Stop to stop):")
count = 2
test_score = input("Test score 1: ")
tuple1 = tuple1 + (test_score,)
while not test_score == "stop" and not test_score == "Stop":
test_score = input("Test score " + str(count) + ": ")
count = count + 1
tuple1 = tuple1 + (test_score,)
last_item = len(tuple1) - 1
tuple1 = tuple1[:last_item]
write_to_file(tuple1)
def read_from_file():
with open('student_info.txt', 'r') as f:
f_contents = f.read()
print(f_contents, end=" ")
And here's my calls in the main section:
open("student_info.txt", "w").close()
student_name = ""
get_student_info("Jenny: ")
get_student_info("Dave: ")
get_student_info("Sammy: ")
get_student_info("Brooke: ")
read_from_file()
My student_info.txt just ends up reading "Brooke:" and then the data added to the tuple on the last call.
If you want to append to a file you need to change the ‘w’ to an ‘a’ for append when you want to write to the file.

issues looping back to start of program

I am having troubles looping back to the start of the program. I am asked to ask the user if they would like to enter another file, if they say yes it will bring them back to the start of the program to input a file name. When I do this, it just restates the previous file entered. I was wondering how to make it so it would ask for another file input. Here is my code:
def main ( ):
file = input("Enter Name of input file: ")
inputfile = open(file, "r")
total = 0
count = 0
num_list = []
#Read and display the file's contents
for line in inputfile:
number = int(line)
total += number
count += 1
num_list.append(number) # append current number to the list
max_number = max(num_list) # get max value from the list of numbers
min_number = min(num_list) # get min value from the list of numbers
range_of_list = (max_number - min_number)
# close the file
inputfile.close()
while True:
print("File Name: ",inputfile.name)
print("Sum: ", total)
print("Count: ", count)
print("Average: ", total / count)
print("Maximum: ", max_number)
print("Minimum: ", min_number)
print("Range: ", range_of_list)
perform_again = input("Would you like to evaluate another file of numbers? (yes/no): ")
if (perform_again == "yes"):
continue
else:
break
main ( )
Your while loop is wrapped around the print statements, so it will just keep printing again and again.
Have it at the start, like the following:
def main():
while True:
file = input("Enter Name of input file: ")
inputfile = open(file, "r")
total = 0
count = 0
num_list = []
# Read and display the file's contents
for line in inputfile:
number = int(line)
total += number
count += 1
num_list.append(number) # append current number to the list
max_number = max(num_list) # get max value from the list of numbers
min_number = min(num_list) # get min value from the list of numbers
range_of_list = (max_number - min_number)
# close the file
inputfile.close()
print("File Name: ", inputfile.name)
print("Sum: ", total)
print("Count: ", count)
print("Average: ", total / count)
print("Maximum: ", max_number)
print("Minimum: ", min_number)
print("Range: ", range_of_list)
perform_again = input(
"Would you like to evaluate another file of numbers? (yes/no): ")
if (perform_again == "yes"):
continue
else:
break
main()

finding the minimum, maximum and average of different list in a 2D matrix (two-dimensional) in python

I'm trying to find the min, max, and average of each student after(or within) the matrix. How would I get access to the list of each student's scores within the loop iteration? I've started with finding the minimum within the function(findlowest()) but can't figure out how to get just 1 student's exam scores at a time.
studentExam = 5
minMaxScore = 5
def main():
global studentName, studentExam, score, scoreList, examScoreMaxList, min, max
def ValidateUser(score):
while score < 0 or score > 100:
score = float(input("Invalid input, please try again"))
return score
def getStudentInfo():
studentName = int(input("enter the number of student: "))
# studentExam = int(input("how many exam scores: "))
# Initialize matrix
matrix = []
# For user input
for i in range(studentName): # A for loop for row entries
scoreList = []
scoreList.append(input("enter name of students " + str(i + 1) + ": "))
for j in range(studentExam): # A for loop for column entries
score = float(input("enter exam " + str(j + 1) + ": "))
score = ValidateUser(score)
scoreList.append(score)
matrix.append(scoreList)
print(matrix)
# for printing
for i in range(studentName):
for j in range(studentExam+1):
print(matrix[i][j], end=" ")
print()
getStudentInfo()
def findLowest():
minlist = []
min = minlist[0]
for i in studentExam[0:5]:
if i < min:
min = i
print("the minimum number is: ", min)
findLowest()
I would like the code to display something similar to the following:
Mike H: min score - 78
max score - 94
avg score - 85
Sarah G: min score - 78
max score - 94
avg score - 85
This should do it. You just needed a nested for loop.
scores = [["Mike", 100, 98, 43, 56, 43], ["John", 95, 32, 79, 75, 67]]
for arr in scores:
#arr = ["Mike", 100, 98, 43, 56, 43] or ["John", 95, 32, 79, 75, 67]
min = None
max = None
sum = 0
studentName = None
for i in arr:
if type(i) != str:
if not min or i < min:
min = i
if not max or i > max:
max = i
sum += i
else:
studentName = i
avg = sum/5
print(studentName + ": \t min score - " + str(min))
print("\t max score - " + str(max))
print("\t avg score - " + str(avg))
print()
Mixing different types of data in a list can be confusing. I keep them separated - student name is the key in the dictionary, the scores list is value.
Also, regarding the first half of the sample code, a general best practice is to avoid using global variables, except for constant values.
def getStudentInfo():
studentName = int(input("enter the number of student: "))
# studentExam = int(input("how many exam scores: "))
# Initialize matrix
matrix = {}
# For user input
for i in range(studentName): # A for loop for row entries
name = input("enter name of students " + str(i + 1) + ": ")
matrix[name] = []
for j in range(studentExam): # A for loop for column entries
score = float(input("enter exam " + str(j + 1) + ": "))
score = ValidateUser(score)
matrix[name].append(score)
print(matrix)
return matrix
data = getStudentInfo()
def findInfo(data, name = None):
def findInfoByName(name):
if name in data:
scores = data[name]
minScore = min(scores)
maxScore = max(scores)
avgScore = sum(scores) / len(scores)
print(f"{name}:\tmin score - {minScore}")
print(f"\tmax score - {maxScore}")
print(f"\tavg score - {avgScore}")
if name is None:
for name in data:
findInfoByName(name)
else:
findInfoByName(name)
findInfo(data)

How to repeat blocks of code in Python

I've created a code that allows a user to view the average score of the values that are in the file. In Example the Text File would look like the following:
Text File For Class 1: it is similar for each text file ; 2 and 3. just different names and values
Matt 2
Sid 4
Jhon 3
Harry 6
There are 3 classes altogether in which the user is prompted to choose which class they want to preview.
Code:
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
main_menu()
option = input("option [avg]: ")
option_class = input("class: ")
one = "1.txt"
two = "2.txt"
three = "3.txt"
if option.lower() == 'avg' and option_class == '1':
with open(one) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '2':
with open(two) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '3':
with open(three) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
Question
If i wanted to Keep Repeating the code above so that the user can keep using it until they want to exit. so, is it possible to put the code into a while loop and only stop the code if the user wants to, i.e the user is prompted if they want to choose another option and class.
NB: there will be other options such as alphabetical order however right now i only want to know how to do it for the average section.
Best thing you can do is to make a loop for user input and write a function for listing the file.
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
main_menu()
option = ""
options = ["1", "2", "3"]
one = "1.txt"
two = "2.txt"
three = "3.txt"
def read_text_file(file): # standalone function for viewing files to reduce duplicate code
file += ".txt"
with open(file) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
while True:
option = input("option [avg]: ").lower()
if option == "exit":
break # checks if user want to exit a program
else:
option_class = input("class: ")
if option == 'avg' and option_class in options:
read_text_file(option_class)
else:
print("nothing to show, asking again")
print("end of program")
As I mentioned in the comment section, you should leverage the power of functions here. By breaking down your components to manageable pieces, you actually afford yourself readability and flexibility. See code below, where I have two functions, one for averages and one for totals.
def get_class_average(class_number):
filename = "{0}.txt".format(class_number)
try:
with open(filename) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
return avg
except:
print "No file with that name found."
def get_class_total(class_number):
filename = "{0}.txt".format(class_number)
try:
with open(filename) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
return b
except:
print "No file with that name found."
def check_class_number(string_input):
try:
int(string_input)
return True
except ValueError:
return False
if __name__ == "__main__":
while True:
input_val = raw_input(
"Enter class number (enter 'exit' to quit program): ")
if input_val == 'exit':
break
if check_class_number(input_val): # If it's a valid class number.
method = raw_input("Enter method: ")
if method == 'avg':
avg = get_class_average(int(input_val))
print "The average of Class {0} is {1}".format(input_val, avg)
elif method == 'sum':
total = get_class_total(int(input_val))
print "The total of Class {0} is {1}".format(input_val, total)
else:
print "That is not a valid class number."
continue
Sample run:
The really fun part here is that you can even refactor get_class_average and get_class_total to be a single function that checks if the passed in method is avg or sum and returns the respective values from there (this is easily doable since you have practically the same lines of code for both functions, get_class_average just has an extra division involved).
Have fun.
Yes, you can just put your code within a while-loop and prompt the user for input:
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
# End main_menu()
one = "1.txt"
two = "2.txt"
three = "3.txt"
keepGoing = True
while(keepGoing):
main_menu()
option = input("option [avg]: ")
option_class = input("class: ")
if option.lower() == 'avg' and option_class == '1':
with open(one) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '2':
with open(two) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '3':
with open(three) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
# Prompt user for input on whether they want to continue or not:
while(True):
keepGoingStr = input("Would you like to continue? (Y/N)\n>>> ").lower()
if(keepGoingStr[0] == 'y'):
# Keep going
keepGoing = True
break
elif(keepGoingStr[0] == 'n')
# Stop
keepGoing = False
break
else:
print("Sorry, your input did not make sense.\nPlease enter either Y or N for yes or no.")
# end if
# end while - keep going input
# End While(keepGoing)
As mentioned in the comments, though, you should consider breaking up your code into functions.

why am I getting this python syntax indexerror

I am new to python and programming in general. I have received many syntax errors in my program. most have been Index errors. When I run it now what I get is:
"Traceback (most recent call last):
File "C:\Python33\HW3 playing around.py", line 133, in <module>
Main()
File "C:\Python33\HW3 playing around.py", line 32, in Main
EmployeeNumbers()
File "C:\Python33\HW3 playing around.py", line 69, in EmployeeNumbers
Sal[Index] = float(input("Enter Employee salary here: "))
IndexError: list assignment index out of range"
I have no idea how to solve both this error and many others that this program has, any help would be appreciated.
-Jacob
# Description: This program will Calculate the Average, Maximum, and Minimum Salaries of employees
#Declare Variables
EmpNum = 0
SalAVG = 0
Index = 0
SalTot = 0
# Start Main
def Main():
# Get Number of employees
EmpNum = int(input("Enter the number of employee's here: "))
if EmpNum <=0:
print("Please enter positive number")
while Index < EmpNum:
# Call EmployeeNames
global Name
global Index
global SalTot
Name = [Index]
EmployeeNames()
# Call EmployeeNumbers
global Sal
Sal = [Index]
EmployeeNumbers()
# Calculate SalTot
SalTot = SalTot + Sal[Index]
# Increase Index
Index = Index + 1
# Calculate and output AVG
SalAVG = SalTot / Index
print("The average salary is $", SalAVG)
# Call and output Maximum
Maximum()
print("The highest paid employee is ", EmpName, " With a salary of $")
# Call and output Minimum
global Temp
global Switch
Minimum
print("The Lowest paid employee is ", EmpName, " With a salary of $")
# Arrays
# EmployeeNames array
def EmployeeNames():
# Bind global parts
global Name
global Index
# Run EmployeeNames
Name[EmpNum] = str(input("Enter employee name here: "))
# EmployeeNumbers Array
def EmployeeNumbers():
#Bind Global parts
global Sal
#Run EmployeeNumbers
Sal[Index] = float(input("Enter Employee salary here: "))
if Sal[EmpNum] > 200000:
print("Please enter lower salary")
Sal[EmpNum] = float(input("Enter Employee salary here: "))
if Sal[EmpNum] < 0:
print("Please enter positive number")
Sal[EmpNum] = float(input("Enter Employee salary here: "))
# Maximum array
def Maximum():
# Bind global parts
global Temp
global Switch
global Name
Index = 1
Temp = 0
Switch = 1
while Switch > 0:
Index = 1
if Sal[Index] > Sal[Index + 1]:
# Call NameSwitch
global TempName
global Name
NameSwitch()
Temp = Sal[Index]
Sal[Index] = Sal[Index + 1]
Sal[Index + 1] = Temp
Switch = Switch + 1
Index = Index + 1
Switch = 1
# Minimum array
def Minimum():
# Bind global parts
global Temp
global Switch
global Name
Index = 1
Temp = 0
Switch = 1
while Switch > 0:
Index = 1
if Sal[Index] < Sal[Index + 1]:
# Call NameSwitch
global TempName
global Name
NameSwitch()
Temp = Sal[Index]
Sal[Index] = Sal[Index + 1]
Sal[Index + 1] = Temp
Switch = Switch + 1
Index = Index + 1
Switch = 1
# NameSwitch array
def NameSwitch():
#Bind global parts
global TempName
global Name
TempName = ""
TempName = Name[Index]
Name[Index] = Name[Index + 1]
Name[Index + 1] = TempName
Main()
I'm not going to fix your code, but your problem can be simplified to:
>>> some_list = []
>>> some_list[0] = "Hello World"
IndexError: list assignment index out of range
To fix it, you need to either start the list with an initial size:
>>> some_list = [None]
>>> some_list[0] = "Hello World"
Or append to the empty list:
>>> some_list = []
>>> some_list.append("Hello World")
Your major problem stems from the use of global variables. Instead of creating global variables, define your function with the variables as arguments like this:
def Maximum(Temp,Switch,Name):
Then call the function like this
Maximum(Temp,Switch,Name)
That way you can keep track of everything your function will need when defining it.
Back to your error, the problem is that Index is not defined in the function. recreate the function header like so:
def EmployeeNumbers(sal,index):
and in main, call it like this:
EmployeeNumbers(sal, index)
Last, define all of your variables inside main, so you do not need to pass them into main when you call it.

Categories

Resources