How can I read from a file while differentiating the variables? - python

I just started studying Python and I have homework that I don't know how to begin with.
I have to read info about the employees of a company: name, age, occupation, salary, years_in_the company from a (txt) file. They are found on separate lines, and are split by a tab, for example:
Helen 20 Network Designer 5449 9
Jasmine 40 Software Architect 2536 1
Phoebe 28 Software Engineer 2627 7
Aysha 34 Software Developer 6441 3
Now, with this info I have to create a few functions like the average age of the employees, best-paid job, best-paid employee and so on. I do not know how to properly read the data from the file and how to implement the functions. I was thinking to define the functions at first, and then read all the data from the file, but a friend of mine told me that I could define each function and inside it I could read the necessary data.
For example, if I were to calculate the average age of the employees, I was thinking about doing it like this:
def avg(*args):
count = len(args)
if args > 0:
age_sum = 0
for i in args:
age_sum += i
return age_sum / count
else:
return 0
The problem is, I don't know how to fetch the proper data to the function. Can anyone please help me understand how to do it properly?

This is the one way, but there might best way than this to do that, but at least this will help you to deal with your problem. You can optimize the code plus you can change the variable from int to float for better coverage of avg etc and there should not be an empty line between lines in the file.
#print all detail
def print_all():
file = open("data.txt","r")
for line in file:
fields = line.split(" ")
print ("name "+ fields[0])
print ("age "+ fields[1])
print ("occupation "+ fields[2])
print ("type occupation "+ fields[3])
print ("salary "+ fields[4])
print ("years_in_the_company "+ fields[5])
file.close()
# avg salary
def avg__salary(employ = "salary" ):
file = open("data.txt","r")
avg=0
for salary in file:
salary_field = salary.split(" ")
avg=avg+int(salary_field[4])
file.close()
return avg
# avg age
def avg__age(employ = "age" ):
file = open("data.txt","r")
avg_age=0
for age in file:
age_field = age.split(" ")
avg_age=avg_age+int(age_field[1])
file.close()
return avg_age
# best paid job
def best_paid(employ = "paid" ):
file = open("data.txt","r")
bestpaid=0
for age in file:
age_field = age.split(" ")
if bestpaid < age_field[4]:
bestpaid=age_field[4]
file.close()
return bestpaid
number_of_lines=open('data.txt', 'r').read().count("\n")
print("All employ detail")
print_all()
print("Avg salary is",avg__salary()/number_of_lines)
print("Avg age is",avg__age()/number_of_lines)
print("Best paid is",best_paid())

Related

How can I send a routine email using a list as input?

I'm trying to write code in Python to help with sending an email that I send about twice a week, with the same format every time and just a few elements that differ between emails, so I wrote the following code to help with this:
def visitor():
visitors = []
number_of = int(input("How many visitors are you signing in? "))
time = input("What time are they coming? ")
comments = """
Please type the name of the first visitor, and their nationality on the next line, the name of the second visitor
and their nationality on the next line, until you wrote down all the names and nationalities.
If you wanna stop the program and execute the code with the names & nationalities, just type quit
"""
print(comments)
name, i = "", 1
while name != "quit":
name = str(input("Ignore: "))
visitors.append(name)
visitors = visitors.pop(-1)
email = f"""
Hello,
I have {number_of} visitors coming today at {time}.
Name: {visitors[i]}
Nationality: {visitors[i + 1]}
"""
for i in range(len(visitors)):
to_add = f"""
Name: {visitors[i]}
Nationality: {visitors[i + 1]}
"""
email += to_add
ending = "Awaiting your approval\nThank you"
email += ending
return email
visitor()
However, upon running this code, I run into a problem in line 25, saying "Index out of range" ( line 25 is Nationality: {visitors[i + 1]} ). This normally shouldn't happen since the list has more than one element. Can someone help with this?
P.S. I have another, way longer code written for this that works, but I wanted to try and improve it by making it less sloppy.
The visitors list is acceeded at offset i+1, and i go up to len(visitors)-1 (upper limit specified for the loop through range()), so there is an access out of range when i = len(visitors) - 1

Assigning worker names to groups based on the number of days they've worked

This will be hard to explain but please bare with me. I'm currently trying to complete a question for an online course and I have literally no idea what to do. The scenario of the question places me as a programmer in an office that needs to create a program assigning specific staff members that have attended a conference. The task gave me two text files; one text file titled "confPack.txt" that reads
Basic conference pack
Bonus conference pack
And another titled "employees.txt" that reads:
Williams,Mary,Y
Nguyen,Vinh,,Y
Kingsley,Margret
Kline,Bob,Y,Y
Mitchell,Frank,Y
Lowe,Elizabeth,Y,Y
Basically, I need to assign certain staff members to their appropriate group/"pack" based on how many days they have attended the conference. The "Y"'s in the employee.txt file represents the amount of days they have attend (one Y = one day of attendance).
The course question itself wants me to access the confpack.txt file and read the records into an array , access the employees.txt file and loop through the records (checking for the end of file) and use logical operators to select the appropriate conference attendees. They said it should be displayed like so:
Report date: [dd/mm/yyyy] *i've already displayed the time correctly
Attendee: [Surname, first name] Pack/s: [1 or 2 days pack], [both days pack]
And here is what my code looks like so far:
import datetime
dTime = datetime.datetime.now()
confFile = open("confPack.txt", "r+")
print("Report Date: "+ dTime.strftime("%d/%m/%Y"))
print(confFile.read())
with open("employees.txt", "r") as f:
data = f.readlines()
for line in data:
words = line.split(",")
print(words)
confFile.close()
Any help is appreciated. And if you're wondering why I can't contact my course teachers for help, believe me when I say that they are never online.
Edit: In regards #Adirio
I want the output to look like this:
Report Date: 7/9/2020
Attendee: [Williams, Mary] Pack/s: [Basic Conference Pack]
Attendee: [Nguyen, Vinh] Pack/s: [Basic Conference Pack]
Attendee: [Kingsley, Margret] Pack/s: [N/A]
Attendee: [Kline, Bob] Pack/s: [Bonus Conference Pack]
Attendee: [Mitchell, Frank] Pack/s: [Basic Conference Pack]
Attendee: [Lowe, Elizabeth] Pack/s: [Bonus Conference Pack]
Edit #2: Thanks again #Adirio for the answer. However, I actually needed to access the confPack.txt file which reads:
Basic Conference Pack
Bonus Conference Pack
and the print out either the Basic or Bonus conference Pack for its employee.
from datetime import datetime
class Employee:
def __init__(self, surname, name, *args):
self.name = name.strip()
self.surname = surname.strip()
self.days = 0
for arg in args:
if arg.strip() == 'Y':
self.days += 1
now = datetime.now()
print("Report Date: " + now.strftime("%d/%m/%Y"))
#Here i've tried making a .readlines variable to print out the specific conference pack
conf = open("confPack.txt")
all_lines = conf.readlines()
with open("employees.txt", "r") as f:
employees = []
for line in f.readlines():
if len(line.strip()) != 0:
employees.append(Employee(*line.split(",")))
for employee in employees:
print(f'Attendee: [{employee.surname}, {employee.name}]', end=' ')
if employee.days == 2:
print("Pack/s: [" + all_lines[2]+"]")
elif employee.days == 1:
print("Pack/s: [" + all_lines[0]+"]")
else:
print("Pack/s: [N/A]")
Output:
Report Date: 09/09/2020
Attendee: [Williams, Mary] Pack/s: [Basic conference pack
] #As you can see, it prints on a new line
Attendee: [Nguyen, Vinh] Pack/s: [Basic conference pack
]
Attendee: [Kingsley, Margret] Pack/s: [N/A]
Attendee: [Kline, Bob] Pack/s: [Bonus conference pack]
Attendee: [Mitchell, Frank] Pack/s: [Basic conference pack
]
Attendee: [Lowe, Elizabeth] Pack/s: [Bonus conference pack]
Process finished with exit code 0
First I will clean your original code a bit, removing the file you are opening and closing for nothing and using the a with clause for the other as it is a very healthy pattern.
from datetime import datetime
now = datetime.now()
print("Report Date: " + now.strftime("%d/%m/%Y"))
with open("confPack.txt", "r+") as confFile:
print(confFile.read())
with open("employees.txt", "r") as f:
for line in f.readlines():
words = line.split(",")
print(words)
Now let's get to work. We will create a class that represents each employee:
class Employee:
def __init__(self, surname, name, *args):
self.name = name
self.surname = surname
self.days = 0
for arg in args:
if arg.strip() == 'Y':
self.days += 1
The __init__ method accepts the arguments as they are read from the file (surname, name, and a sequence of 'Y'). The name and surname are assigned directly while the rest of the arguments are stored in a list called args. We loop through this list adding 1 day to the day counter if it is equal to 'Y'. The .strip() part removes leading and trailing whitespaces so that we can compare to 'Y' safely.
So all together:
from datetime import datetime
class Employee:
def __init__(self, surname, name, *args):
self.name = name.strip()
self.surname = surname.strip()
self.days = 0
for arg in args:
if arg.strip() == 'Y':
self.days += 1
print("Report Date: " + datetime.now().strftime("%d/%m/%Y"))
with open("confPack.txt", "r+") as f:
packs = ['N/A']
for line in f.readlines():
if len(line.strip()) != 0:
packs.append(line.strip())
with open("employees.txt", "r") as f:
employees = []
for line in f.readlines():
if len(line.strip()) != 0:
employees.append(Employee(*line.split(",")))
# Do whatever you need with the employee list
for employee in employees:
print(f"Attendee: [{employee.surname}, {employee.name}] Pack/s: [{packs[employee.days]}]")
We could also make the part where we open the files shorter by using list comprehensions:
with open("confPack.txt", "r+") as f:
packs = ['N/A'] + [line.strip() for line in f.readlines() if len(line.strip())]
with open("employees.txt", "r") as f:
employees = [Employee(line.split(",")) for line in f.readlines() if len(line.strip())]

Python List Index Ouf Of Range In IF Statement

So i have multiple patients' information stored in database.txt and i want to retrieve the data from the file into a list.
And the system prompt for patient's id to search and display other information of the patient such as Name, Age, Group & Zone.
However, i'm getting error from line 12, but the similar syntax in line 17 is able to run without problem.
search_keyword = input() # Asks for patient's name or id (either one)
with open("database.txt", "r") as database:
for data in database:
for patients in data.split('|'):
patient_details = []
for details in patients.split(','):
patient_details.append(details)
print(patient_details) # test
print(len(patient_details) # test
print(patient_details.index('Patient001')) # test
print(patient_details[4]) # test
if search_keyword == patient_details[0] or search_keyword == patient_details[4]: # error occured here, where it says list index out of range.
print("Name: " + patient_details[0])
print("Age: " + patient_details[1])
print("Group: " + patient_details[2])
print("Zone: " + patient_details[3])
print("ID: " + patient_details[4]) # no error here, patient_details[4] is able to display patient's id
database.txt
John,18,A,1,Patient001|Nick,20,F,9,Patient002
Test command for line 8,9, 10 and 11:
Line 8: [John, 18, A, 1, Patient001]
Line 9: 5
Line 10: 4
Line 11: IndexError: list index out of range
Can someone explain why this is happening, and any solutions regarding this issue without using any imported modules? Thank you for any assistance.
Imo a very good use-case for a named tuple:
from collections import namedtuple
text = "John,18,A,1,Patient001|Nick,20,F,9,Patient002"
# build database
Patient = namedtuple('Patient', ['name', 'age', 'group', 'zone', 'id'])
db = [Patient(*patient) for entry in text.split("|") for patient in [entry.split(",")]]
# Asks for patient's id
search_keyword = input("Please give an ID: ")
# query the database
result = [patient for patient in db if patient.id == search_keyword]
# or patient.id.startswith(), etc.
print(result)
Without any imported modules, you could use
text = "John,18,A,1,Patient001|Nick,20,F,9,Patient002"
# build database
db = [entry.split(",") for entry in text.split("|")]
search_keyword = input("Please give an ID: ") # Asks for patient's id
# query the database
result = [patient for patient in db if patient[4] == search_keyword]
print(result)
I see no flaw in the code. Although, I can point out a few ways to optimise it :
patient_details = dict()
with open("database.txt", "r") as database:
for data in database:
for patients in data.split('|'):
patients = patients.split(',')
patient_details[patients[4]] = patients[0:4]
search_keyword = input() # Asks for patient's id
if patient_details.get(search_keyword, None):
patient_detail = patient_details[search_keyword]
print("Name: " + patient_detail[0])
print("Age: " + patient_detail[1])
print("Group: " + patient_detail[2])
print("Zone: " + patient_detail[3])
print("ID: " + search_keyword)
Using map instead of a linear search would allow you to search optimally.

Python - Write an array to csv / txt and then read

So if I have the following code:
database = []
Name = input("What's the members name?")
MT = input("What membership type?")
DOB = input("What is the member DOB?")
DJ = (now.day ,"/" , now.month, "/", now.year)
year1 = int(now.year)
month1 = int(now.month)
day1 = int(now.day)
ry = int(year1 + 1)
rm = month1
rd = day1
renewal = (day1, month1, year1 + 1)
details = ["Name:", Name, "Membership Type:", MT, "Date of Birth:", DOB, "Date Joined:", DJ,"Renewal Date:", renewal, "Renewal Year:", ry]
database.append(details)
menu()
How would I go about saving (database) to a text file / csv file to be read later.
I have tried pickle but the issue is I need to be able to get each part of the array seperate.
For example if I type:
print(database[1])
I will return all Names stored as "Name", however if I were to write the file using pickle when I bring it back in then
print (database[1])
now shows the entirety of the second user added. I need to be able to save (database) and have it in the same format when read back in.
Expected output using JSON or Pickle(assuming the first user inputted name as "Jeff" and second inputted name as "John")
print (database[1])
Jeff
John
Actual output:
["Name:", John, "Membership Type:", MT, "Date of Birth:", DOB, "Date Joined:", DJ,"Renewal Date:", renewal, "Renewal Year:", ry]
Sorry for the bad explanation I'm new to python.
It seems you are creating an array of records. Try accessing the data in this way:
print(database[0][1]) #[0] for the first record, [1] for second item
print(database[1][1]) #second user, second item

Python/CSV Read Data

My program shown below has the goal of outputting statements based off two criteria:(Year and Location) Once that was accomplished, my next goal is to match year with Yearlink and Location with location. location and year are both input statements. The output should be a statement that outputs values from that row. For some reason, I always receive an error about too many values to unpack. Also when I fix that error, it never outputs anything for that section of the program. The first part of program is outputting correctly. Second part is either giving me Value Error or not outputting at all. My excel sheet is posted if anyone wants a better idea of what I am talking about. Anyway I tried everything but nothing was working for me.
Traceback (most recent call last):
File "C:/Users/RoszkowskiM/Desktop/win4.py", line 134, in <module>
for From,To,Max,Min in data:
ValueError: too many values to unpack
-
LOAD_GEN_DATAFILE = 'C:\Users\RoszkowskiM\Desktop\Data_2016.csv' # CSV File to Read
# read the entire CSV into Python.
# CSV has columns starting with Year,busnum,busname,scaled_power,tla,location
data = list(csv.reader(open(LOAD_GEN_DATAFILE)))
mydict = {}
for row in data:
Year,busnum,busname,scaled_power,tla,Location,Yearlink,From,To,Max,Min = row[0:12]
#If this is a year not seen before, add it to the dictionary
if Year not in mydict:
mydict[Year] = {}
busses_in_year = mydict[Year]
if Location not in busses_in_year:
busses_in_year[Location] = []
#Add the bus to the list of busses that stop at this location
busses_in_year[Location].append((busnum,busname,scaled_power))
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------
#User Input Statement
year = raw_input("Please Select Year of Study: ")
print("\n")
commands = ["Millwood-Buchanan", "Astoria-East-Corona", "Bronx", "DUNWOODIE-North-Sherman_Creek",
"Vernon", "Greenwood-StatenIsland","West_49th","East_13th","Staten_Island","East_River",
"East_View","DUNWOODIE-SOUTH","Corona-Jamaica","Astoria-East-Corona-Jamaica",
"Astoria-West-Queensbridge-Vernon","Astoria-West-Queensbridge"]
max_columns = 50
for index, commands in enumerate(commands):
stars_amount = max(max_columns - len(commands), 0)
row = "# {} {}({})".format(commands, "." * stars_amount, index + 1)
print(row)
location=raw_input(" \n The list above show the TLA Pockets as well as the ID numbers assigned to them ()\n\n Please enter the ID #: ")
print("\n")
Year=year
Location=location
if Year in mydict and Location in mydict[Year]:
busses_in_year = mydict[Year]
print("Here are all the busses at that location for that year and the new LOAD TOTAL: ")
print("\n")
#Busnum, busname,scaled_power read from excel sheet matching year and location
for busnum,busname,scaled_power in busses_in_year[Location]:
scaled_power= float(scaled_power)
busnum = int(busnum)
print('Bus #: %d\t' % busnum ,'Area Station: %s\t'% busname,'New Load Total: %d MW\t' % scaled_power)
else:
exit
-
for row in data:
Year,busnum,busname,scaled_power,tla,Location,Yearlink,From,To,Max,Min = row[0:11]
if Yearlink==year and Location==location:
for From,To,Max,Min in data:
From=int(From)
To=int(To)
Max=float(Max)
Min=float(Min)
print('From Bus #: %d\t' % From ,'To Bus #: %d\t'% To,'VMAX: %d pu\t' % Max, 'VMIN: %d pu\t' % Min)
else:
exit
You are iterating over data to get the rows, but then you iterate again over data to get From, To, Max and Min, which you had already unpacked. That line doesn't make sense. This should work:
for row in data:
data_location, year_link, from_, to, max_value, min_value = row[5:11]
output = 'From Bus #: {}\tTo Bus #: {}\tVMAX: {} pu\tVMIN: {} pu\t'
if year_link == year and data_location == location:
print(output.format(from_, to, max_value, min_value))
I simplified a bit and changed the variable names, but the only thing you have to do is remove that spurious for line.

Categories