Calculating the average of specific numbers in a mixed text file? - python

I have a program that reads a file that has student names, IDs, majors, and GPAs in it.
For example (there is much more to the file):
OLIVER
8117411
English
2.09
OLIVIA
6478288
Law
3.11
HARRY
5520946
English
1.88
AMELIA
2440501
French
2.93
I have to figure out:
which medicine majors made the honor roll and
the average GPA of all the math majors
All I have right now is the list of medicine majors that made honor roll. I have no idea how to start calculating the average GPA of math majors. Any help is appreciated, and thanks in advance.
This is the code I currently have:
import students6
file = open("students.txt")
name = "x"
while name != "":
name, studentID, major, gpa = students6.readStudents6(file)
print(name, gpa, major, studentID)
if major == "Medicine" and gpa > "3.5":
print("Med student " + name + " made the honor roll.")
if major == "Math":
Here is the students6.py file that is being imported:
def readStudents6(file):
name = file.readline().rstrip()
studentID = file.readline().rstrip()
major = file.readline().rstrip()
gpa = file.readline().rstrip()
return name, studentID, major, gpa

You need to represent the data, currently you are returning tuples from reading the file.
Store them in a list, create methods to filter your students on theire major and one that creates the avgGPA of a given student-list.
You might want to make the GPA a float on reading:
with open("s.txt","w") as f:
f.write("OLIVER\n8117411\nEnglish\n2.09\nOLIVIA\n6478288\nLaw\n3.11\n" + \
"HARRY\n5520946\nEnglish\n1.88\nAMELIA\n2440501\nFrench\n2.93\n")
def readStudents6(file):
name = file.readline().rstrip()
studentID = file.readline().rstrip()
major = file.readline().rstrip()
gpa = float(file.readline().rstrip()) # make float
return name, studentID, major, gpa
Two new helper methods that work on the returned student-data-tuples:
def filterOnMajor(major,studs):
"""Filters the given list of students (studs) by its 3rd tuple-value. Students
data is given as (name,ID,major,gpa) tuples inside the list."""
return [s for s in studs if s[2] == major] # filter on certain major
def avgGpa(studs):
"""Returns the average GPA of all provided students. Students data
is given as (name,ID,major,gpa) tuples inside the list."""
return sum( s[3] for s in studs ) / len(studs) # calculate avgGpa
Main prog:
students = []
with open("s.txt","r") as f:
while True:
try:
stud = readStudents6(f)
if stud[0] == "":
break
students.append( stud )
except:
break
print(students , "\n")
engl = filterOnMajor("English",students)
print(engl, "Agv: ", avgGpa(engl))
Output:
# all students (reformatted)
[('OLIVER', '8117411', 'English', 2.09),
('OLIVIA', '6478288', 'Law', 3.11),
('HARRY', '5520946', 'English', 1.88),
('AMELIA', '2440501', 'French', 2.93)]
# english major with avgGPA (reformatted)
[('OLIVER', '8117411', 'English', 2.09),
('HARRY', '5520946', 'English', 1.88)] Agv: 1.9849999999999999
See: PyTut: List comprehensions and Built in functions (float, sum)
def prettyPrint(studs):
for name,id,major,gpa in studs:
print(f"Student {name} [{id}] with major {major} reached {gpa}")
prettyPrint(engl)
Output:
Student OLIVER [8117411] with major English reached 2.09
Student HARRY [5520946] with major English reached 1.88

Related

Creating emails while accounting for two first names when using input()

My code below works as long as all of the student's name consists of only two names - ex. Julie Andrews. But, when generating the student's emails, I'm trying to account for the students who have two first names - ex. Mary Jane Stewart. I want it to output something like MJStewart123#gmail.org, vs. what my current code will print, which is MJane123#gmail.com - totally ignoring the student's last name.
After hours of researching Google, I have tried updating my create_emails fx to change my original variable first_last = name.split(" ") to something like first, middle, last = name.split(" ") or first_last = name.split(" ", 2) while also, respectively, updating the line utilizing the attribute .append from its original to student_emails.append(first_last[0][0] + first_last1 + first_last[2]+ last_three_sid + "#gmail.com") or student_emails.append(first[0] + middle[0] + last + last_three_sid + "#gmail.com"). All attempts have obviously returned some form of an error...
The attached Stack Overflow article is the closest thing I could find whose logic might be applicable to what I'm trying to accomplish here, specifically the comment by Manfred, but in reading it, I don't know how to apply what they've done to my program... because I don't quite understand what it is that I'm reading... since I'm such a newbie at all this. I'd appreciate any help you can offer.
student_names = []
def create_names():
count = 1
while count <= 5:
name = input("Enter student name, please. ")
student_names.append(name)
count += 1
create_names()
import random
student_ids = []
def create_ids():
student_id = random.randint(111111,999999)
return student_id
def create_id_list():
for name in student_names:
student_ids.append(create_ids())
create_id_list()
student_emails = []
def create_emails():
for name in student_names:
first_last = name.split(" ")
sid = str(student_ids[student_names.index(name)])
len_sid = len(sid)
last_three_sid = sid[len_sid-3:len_sid]
student_emails.append(first_last[0][0] + first_last[1] + last_three_sid + "#gmail.com") #ignores last index if one is provided.
create_emails()
def student_info():
for name in student_names:
name_pos = student_names.index(name)
print("\n" + "name: " + name)
print("id: " + str(student_ids[name_pos]))
print("email: " + student_emails[name_pos])
student_info()
Finding and first and middle initials in a list of names in python
You could do it like this I guess:
student_names = []
def create_names():
count = 1
while count <= 5:
name = input("Enter student name, please. ")
student_names.append(name)
count += 1
create_names()
import random
student_ids = []
def create_ids():
student_id = random.randint(111111,999999)
return student_id
def create_id_list():
for name in student_names:
student_ids.append(create_ids())
create_id_list()
student_emails = []
def create_emails():
for name in student_names:
email_name = ""
first_last = name.split(" ")
for i, v in enumerate(first_last):
if i > len(first_last)-2:
break
email_name+=v[0]
email_name = email_name+first_last[-1]
sid = str(student_ids[student_names.index(name)])
len_sid = len(sid)
last_three_sid = sid[len_sid-3:len_sid]
student_emails.append(email_name + last_three_sid + "#gmail.com") #ignores last index if one is provided.
create_emails()
def student_info():
for name in student_names:
name_pos = student_names.index(name)
print("\n" + "name: " + name)
print("id: " + str(student_ids[name_pos]))
print("email: " + student_emails[name_pos])
student_info()
Result:
Enter student name, please. Julie Andrews
Enter student name, please. Mary Jane Stewart
Enter student name, please. Jack Hendricks
Enter student name, please. Maria Basset Juliett
Enter student name, please. Marco Hansen
name: Julie Andrews
id: 742536
email: JAndrews536#gmail.com
name: Mary Jane Stewart
id: 823274
email: MJStewart274#gmail.com
name: Jack Hendricks
id: 590875
email: JHendricks875#gmail.com
name: Maria Basset Juliett
id: 982168
email: MBJuliett168#gmail.com
name: Marco Hansen
id: 671240
email: MHansen240#gmail.com
The code is too redundant and could be implemented with some simpler structures.
name construction can use split combined with join function
storage can also use dictionaries to store multiple information about the same object, compared to multiple lists so more concise and efficient
The code itself is not a big problem, mainly the syntax structure requires more skilled,let's encourage each other in our endeavours
try this:
import random
info = []
# You can use for loop if you already know how many times it will loop
for i in range(5):
name = input("Enter student name, please:") # get name
student_id = random.randint(111111, 999999) # get id
name_structure = name.split()
email = "{name_abbr}{last_name}{sid}#gmail.com".format(
name_abbr="".join([item[0] for item in name_structure[:-1]]), # Generate initials
last_name=name_structure[-1], # Generate the last part of the name
sid=str(student_id)[-3:] # Generate the id in the mailbox
)
info.append({"name": name, "id": student_id, "email": email}) # Store to the list, or print directly
# Print Information
for item in info:
print("name:", item["name"])
print("id:", item["id"])
print("email:", item["email"])
print()

Create and store objects in list Python

class Prog:
def __init__(self, name, course, languange):
self.name = name
self.course = course
self.languange = languange
def show(self):
print("Name:", self.name, "\nCourse:", self.course, "\nLanguage:", self.languange, "\n")
#Complete code
Students = []
#Create and store the students info (objects) in the list Students
number_of = int(input("Number of students?: "))
#Complete code
loop = 0
while loop < antal:
print("Name, course language?") #here I want the user to type the name, course and what programming language he/she is studying
print("The following students are now in the system")
#Complete code
I want the output to be:
Number of students?: 2
Name, course, language?
Alan
P1
Python
Name, course, language?
Jane
P2
Python
The following students are now in the system:
Name : Alan
Course : P1
Language : Python
Name : Jane
Course : P2
Language : Python
I can't seem to give self.name, self.course, self.language the input() value in the list Students = []
I did try to .appendto the list but when I write p.Prog(Students)I get this error message TypeError: __init__() missing 2 required positional arguments: 'course' and 'languange'
This is the code I wrote to store values into the list.
Students = []
number_of = int(input("Number of students?: "))
loop = 0
while loop < number_of:
print("Name, course, language?")
name = input()
course = input()
language = input()
loop += 1
p = Prog(Students)
print("Following students are now in the system.")
p.show()
You need to append to Students.
When you call Prog(), you have to provide the 3 values that you just input as parameters. It's not clear why you thought the Students list would be the proper argument there.
Then when you want to list all the students, you have to loop through the Students list.
Students = []
number_of = int(input("Number of students?: "))
for _ in range(number_of):
name = input('Name: ')
course = input('Course: ')
language = input('Language: ')
p = Prog(name, course, language)
Students.append(p)
print("Following students are now in the system.")
for student in Students:
student.show()

Class to collect data from user

I am learning python from scratch and am stuck with classes what I am trying to achieve as follows:
Problem statement: "Collect the data of different students into an array and display."
I am trying to achieve this using classes.
Below is my code which I am trying out. Need help on how to get the values of different question into one single dimensional array.
i.e.
["brittos school", "Ahmedabad", "Francis", "34", " 36", "anthony's school", "Mumbai", "Sam", "45", " 55"]
Where 34 36 are the marks of the subject.
class Mack:
def getmarks(self,numberofsubjects,numberofstudents,sub):
marks=[]
for i in range(numberofstudents):
self.sname=input("Enter your School Name: ")
a.append(marks)
self.city=input("Enter the School City: ")
a.append(marks)
self.name=input("Enter your Name")
a.append(marks)
a=[]
for j in range(numberofsubjects):
a.append(int(input(f"Enter the Marks for {sub[j]} ")))
marks.append(a)
def show(self):
print("My Name is: ",self.name)
print("My City is: ",self.city)
sub=[]
numberofstudents=int(input("Input the number of students"))
numberofsubjects=int(input("Input the number of subjects"))
for i in range(0, numberofsubjects):
ele = input(f"enter the subject name :{i+1}")
sub.append(ele)
ab=Mack()
for i in range(0,numberofstudents):
ab.getmarks(numberofstudents,numberofsubjects,sub)
First of all, you are using the same loop outside the getmarks function and inside it so for example if I input number of students as 2. It will run 4 times which is incorrect. Loop over number of students once. Secondly a is not defined anywhere so if you want the list of all the input I'd suggest creating a as a member variable of this class.
I think this code below is what you need
class Mack:
def getmarks(self,numberofsubjects,numberofstudents,sub):
marks=[]
a = []
for i in range(numberofstudents):
self.sname=input("Enter your School Name: ")
a.append(self.sname)
self.city=input("Enter the School City: ")
a.append(self.city)
self.name=input("Enter your Name")
a.append(self.name)
for j in range(numberofsubjects):
a.append(int(input(f"Enter the Marks for {sub[j]} ")))
marks.append(a)
return a
def show(self):
print("My Name is: ",self.name)
print("My City is: ",self.city)
sub=[]
numberofstudents=int(input("Input the number of students"))
numberofsubjects=int(input("Input the number of subjects"))
for i in range(0, numberofsubjects):
ele = input(f"enter the subject name :{i+1}")
sub.append(ele)
ab=Mack()
result = ab.getmarks(numberofstudents,numberofsubjects,sub)
print(result)
Although this is a very bad approach to do what you are trying to do. What I would suggest is to create a Student Class like.
class Student:
def __init__(self, name, sname, cname, subjects, marks):
self.name = name
self.sname = sname
self.cname = cname
self.subjects = subjects
self.marks = marks
where subjects and marks would lists of subjects and marks. You can also create a dictionary if you want where subject would be key and marks would be value. After that, you can simple create a list of this class and take input for every element of that Student list.

Comparing tuple values from text file in Python 3

I'm aiming to display records of employees with a salary between 2 user inputted values (in a format specified in my function printTuple(data)). So far I use the function choice2() to open the file, read line by line in a for loop, convert the line (which is a string) to an int, then grab the index of the salary so I can compare it to the 2 inputted values (. After that I take the line as a variable in "record" and go to makeTuple to turn it into a tuple, and then finally print it in my desired format inside printTuple.
When I attempt to run the choice2 function I get an error: "local variable 'myTuple' referenced before assignment". However I need to change the myTuple value to an int before I can compare it with the values the user inputted, so I'm not sure how to fix this.
Here is my program:
def makeTuple (employee):
myTuple = employee.split(" ")
(payroll, salary, job_title, *othernames, surname) = myTuple
return(myTuple)
def printTuple (data):
employee_str = "{:<15} {:20} {:<10} {:<15} £{:>1}"
print(employee_str.format(data[-1]+ ",", " ".join(data[3:-1]), data[0], data[2], data[1]))
def choice1():
op_1 = str(input("Please enter a Pay Roll number: "))
file = open(path)
lines = file.readlines()
for line in lines:
if op_1 in line:
record = line.strip()
myTuple = makeTuple(record)
printTuple(myTuple)
def choice2():
op_2a = int(input("Please enter a lower bound for the Salary :"))
op_2b = int(input("Please enter a higher bound for the Salary :"))
file = open(path)
lines = file.readlines()
for line in lines:
myTuple[0] = int(myTuple[0])
if myTuple[0] >= op_2a and myTuple[0] <= op_2b:
myTuple[0] = myTuple[0]
record = line.strip()
myTuple = makeTuple(record)
print(myTuple)
get_file = input(str("Please enter a filename: "))
path = get_file + ".txt"
try:
f = open(path)
except IOError:
print('The file could not be opened.')
exit()
for line in iter(f):
record = line.strip()
myTuple = makeTuple(record)
printTuple(myTuple)
print("\n\nDisplay full details of an Employee with a given payroll number enter: '1'")
print("Display all employees with a salary within a specified range, enter: '2'")
print("Display the first and last name of all employees with a job title, enter: '3'")
print("Quit Program: '4'")
choice = int(input("Choose an option from 1-4: "))
while choice != 1 and choice != 2 and choice != 3 and choice != 4:
print("Incorrect Value, please choose a number from 1-4")
print("\n\nDisplay full details of an Employee with a given payroll number enter: '1'")
print("Display all employees with a salary within a specified range, enter: '2'")
print("Display the first and last name of all employees with a job title, enter: '3'")
print("Quit Program: '4'")
choice = int(input("Choose an option from 1-4: "))
if choice == 1:
choice1()
if choice == 2:
choice2()
if choice == 3:
choice3()
if choice == 4:
exit()
This is the text file I am reading from:
12345 55000 Consultant Bart Simpson
12346 25000 Teacher Ned Flanders
12347 20000 Secretary Lisa Simpson
12348 20000 Wizard Hermione Grainger
12349 30000 Wizard Harry Potter
12350 15000 Entertainer Herschel Shmoikel Krustofski
13123 75000 Consultant Zlatan Ibrahimovic
13124 150000 Manager Gareth Southgate
13125 75000 Manager Juergen Klopp
13126 35000 Lecturer Mike T Sanderson
13127 200000 Entertainer Adele Laurie Blue Adkins
13128 50 Timelord Peter Capaldi
13129 250000 Entertainer Edward Christopher Sheeran
13130 32000 Secretary Wilma Flintstone
Any help is appreciated, thanks in advance.
Your error message (local variable myTuple referenced before assignment) points out the required solution. I have:
reordered (record = line.strip() and myTuple = makeTuple(record) to top of loop)
renamed some variables (myTuple is not very descriptive, and is actually a list anyway, better naming makes code much easier to read and reason about)
heavily commenting (I would not normally comment my own code this much, more as indications of what I have done and why)
Here is the updated code for choice2
def choice2():
lower_bound = int(input("Please enter a lower bound for the Salary :")) # Renamed for clarity
upper_bound = int(input("Please enter a higher bound for the Salary :")) # Renamed for clarity
# The following two lines are repeated multiple times, you should probably read
# the file once and store into a list (or better yet a dictionary
# keyed with pay roll number) and pass it into the function.
file = open(path)
lines = file.readlines()
for line in lines:
record = line.strip()
employee_details = makeTuple(record) # Rename muTuple to employee_details
# OR MORE SIMPLY employee_details = makeTuple(line.strip())
# Now we have the variable we can work with it
salary = int(employee_details[0]) # The only thing we do with the tuple is print it, so no need to modify it
if salary >= lower_bound and salary <= upper_bound:
# This does nothing, so deleted - myTuple[0] = myTuple[0]
print(employee_details) # Or more likely you want to use your custom print function printTuple(employee_details)

Python List in List ("Stuck")

def lists(): #Where list is stored
List = ["Movie_Name",[""],"Movie_Stars",[""],"Movie_Budget",[""]]
print ("Your Movies")
amount_in_list = int(input("How many Movies? "))
x = 1
while x <= amount_in_list:
film = input ("Name of film ... ")
stars = input ("Main stars ...")
Budget = input ("Budget ...")
List.append["Movie_Name"](film)
List.append["Movie_Stars"](stars)
List.append["Movie_Budget"](Budget)
lists()
How do i add the film you enter to the list under the subsetting Movie_Name etc?
A better answer than one which answers your question directly would be: You don't. You definitely need a dictionary for this situation (unless your program develops to a point where you'd prefer creating a custom object)
As a simple demonstration:
def getMovies():
movieinfo = {"Movie_Name": [], "Movie_Stars": [], "Movie_Budget": []}
print ("Your Movies")
amount_in_list = int(input("How many Movies? "))
x = 1
while x <= amount_in_list:
film = input ("Name of film ... ")
stars = input ("Main stars ...")
budget = input ("Budget ...")
movieinfo["Movie_Name"].append(film)
movieinfo["Movie_Stars"].append(stars)
movieinfo["Movie_Budget"].append(budget)
x+=1
return movieInfo
Notice that with a dict you simply use the key string to get the corresponding list (initialized at the start of the function) and append the data as desired.
Edited to provide further information for OP's updated request.
If you want to find a movie's info based on just the movie's name given by the user, you could try something like this:
film = 'The Matrix' # Assuming this is the user's input.
Try:
# The index method will throw an exception if
# the movie cannot be found. If that happens,
# the 'except' clause will execute and print
# the relevant statement.
mIdx = movieinfo['Movie_Name'].index(film)
print '{0} stars {1} and had a reported budget of {2}'.format(
film, movieInfo['Movie_Stars'][mIdx], movieInfo['Movie_Budget'][mIdx])
except ValueError:
print '{0} is not in the movie archives. Try another?'.format(film)
Output:
'The Matrix stars Keanu Reeves and had a reported budget of $80 million'
Or:
'The Matrix is not in the movie archives. Try another?'
I would store the movie information in an object. This way your code will be easier to extend, make changes and reuse. you could easily add methods to your movie class to do custom stuff or add more properties without having to change your code to much.
class Movie:
def __init__(self, name='', actors=[], rating=0 budget=0):
self.name=name
self.actors=actors
self.budget=budget
self.rating=rating
def setName(self, newname):
self.name=newname
def setActors(self, newstars):
self.actors=newstars
def setBudget(self, newbudget):
self.budget=newbudget
def setRating(self, newrating):
self.rating=newrating
# example
mymovies=[]
movie1= Movie('Interstellar',['actor1','actor2','actor3'], 5, 100000)
movie2=Movie()
movie2.setName('other movie')
movie2.setActors(['actor1','actor2','actor3'])
movie2.setBudget(10000)
mymovies.append(movie1)
mymovies.append(movie2)
# or append to your list in a loop

Categories