I am working with file handling exercise.
So my txt file have this content:
List of Sales
Day 1 : 1250.25
Day 2 : 2560.25
Day 3 : 3241.10
Day 4 : 1530.20
Day 5 : 1247.27
Day 6 : 1646.22
Day 7 : 850.25
I want to only get the amount per day and sum it.
OFile = open('sales.txt','r')
file_content = OFile.read()
print(file_content)
import re
get = re.findall(r'[.]', file_content)
amount = []
for n in range(7):
amount.append(get)
total = sum(amount)
print("Total sales Amount: ", "Php", total)
I keep getting Total sales Amount 0
keep it simple and use str.split and str.strip instead of using regex!
In your case (with the input file you have attached)
Exception may raised from the conversion to float (if you have
invalid line or some string that can not be converted to float!
Or line that have no ":" (e.g. the first line in the file) which causes
the split() call to return the same input string as a list of one string (the line)
without spaces.In both cases you want to
skip and continue to next line!
total_sum = 0
with open('sales.txt','r') as fp:
for line in fp:
try:
current_float_num = line.strip().split(":")[1]
current_float_num = float(current_float_num)
# do work on float_num
# for example add it to the accumulative total_sum
total_sum += current_float_num
except (IndexError,ValueError):
continue
I have a text file like this:
month /name/ number/ price
1 John 100 120.00
1 Sean 90 125.00
1 Laura 150 100.00
1 Joseph 95 140.00
1 Pam 91 105.00
2 John 110 120.00
2 Sean 98 100.00
2 Laura 100 100.00
2 Joseph 89 150.00
2 Pam 100 100.00
3 John 100 121.00
3 Sean 90 120.00
3 Laura 97 100.00
3 Joseph 120 110.00
3 Pam 101 100.00
I need to get a specific person's (such as Pam) revenue per month and total revenue in 1,2 and 3 months (number*price). I have the code below and the output below. But I have no idea how to get the total revenue, can anyone give to me some advice or idea?
#This is the code I use
f = input('Enter The File Name:')
sales_data = open("sales.txt",'r')
lines = sales_data.readlines()
m = input('Enter the Manager Name:')
print('Monthly Sales Report for' +' ' + m)
for line in lines:
line = line.split()
tr = (float(line[2]) * float(line[3]))
if m in line:
print(line[0] +' ' + line[2] + ' ' + line[3] +' ' + str(tr))
#This is the output I got
Enter the Manager Name: Pam
Monthly Sales Report for Pam
1 91 105.00 9555.0
2 100 100.00 10000.0
3 101 100.00 10100.0
One possible way to solve your issue is to store all monthly values in a dictionary for a particular manager:
file_name = input('Enter The File Name: ')
manager_summary = {'1':0.0, '2':0.0, '3':0.0}
with open (file_name, 'r') as fin:
lines = fin.readlines()
manager = input('Enter the Manager Name: ')
print('Monthly Sales Report for' +' ' + manager)
for line in lines:
line = line.split()
if manager in line:
manager_summary[line[0]] += float(line[-2])*float(line[-1])
manager_total = 0.0
for key, value in manager_summary.items():
manager_total += value
print(manager_total)
The code reads the input file at once, loops through all the lines in search of the target manager and stores cumulative monthly sales for that manager in a dictionary. The total revenue for 3 month period is then computed by adding cumulative values for each month stored in the dictionary.
There were couple changes with respect to your original code worth noting:
In your code you ask the user for a file name but then you have it hardcoded in the next line - here you use that input file name.
Instead of opening the file with open this code uses with open - with open is a context manager that will automatically close the file for your when closing is needed, something that your were missing in your program.
Cumulative data is stored in a dictionary with keys being month numbers. This allows for having more than one monthly entry per manager.
Variable names are more meaningful. It is generally not recommended to use variables like f, m, it makes the program more bug prone and way less readable. The ones used here are longish, you can always come up with something inbetween.
You can solve this using a dictionary - specifically a defaultdict. You can keep track of a dictionary of people's names to revenue.
First import defaultdict and define a dictionary:
from collections import defaultdict
revenue_dictionary = defaultdict(float)
Then just after you've calculated tr, add this to the dictionary:
revenue_dictionary[line[1]] += tr
At the end of the script, you'll have a dictionary which looks like:
{
'John': 37300.0,
'Sean': 31850.0,
'Laura': 34700.0,
'Joseph': 39850.0,
'Pam': 29655.0
}
And you can access any of these using revenue_dictionary['Pam'], or m instead of 'Pam'.
f = input('Enter The File Name: ')
sales_data = open(f,'r')
lines = sales_data.readlines()
m = input('Enter the Manager Name: ')
print('Monthly Sales Report for ' + m)
TOTAL_REVENUE=0
for line in lines:
line = line.split()
if m in line:
tr = (float(line[2]) * float(line[3]))
TOTAL_REVENUE=TOTAL_REVENUE+tr
print(line[0] +' ' + line[2] + ' ' + line[3] +' ' + str(tr))
print("GRAND TOTAL REVENUE: " + str(TOTAL_REVENUE))
I am trying to format a print statement to align a specific column.
Currently my output is:
0 - Rusty Bucket (40L bucket - quite rusty) = $0.00
1 - Golf Cart (Tesla powered 250 turbo) = $195.00*
2 - Thermomix (TM-31) = $25.50*
3 - AeroPress (Great coffee maker) = $5.00
4 - Guitar (JTV-59) = $12.95
The output I am looking for is:
0 - Rusty Bucket (40L bucket - quite rusty) = $0.00
1 - Golf Cart (Tesla powered 250 turbo) = $195.00*
2 - Thermomix (TM-31) = $25.50*
3 - AeroPress (Great coffee maker) = $5.00
4 - Guitar (JTV-59) = $12.95
Here is the code I am currently using for the print:
def list_items():
count = 0
print("All items on file (* indicates item is currently out):")
for splitline in all_lines:
in_out = splitline[3]
dollar_sign = "= $"
daily_price = "{0:.2f}".format(float(splitline[2]))
if in_out == "out":
in_out = str("*")
else:
in_out = str("")
print(count, "- {} ({}) {}{}{}".format(splitline[0], splitline[1], dollar_sign, daily_price, in_out))
count += 1
I have tried using formatting such as:
print(count, "- {:>5} ({:>5}) {:>5}{}{}".format(splitline[0], splitline[1], dollar_sign, daily_price, in_out))
but have never been able to get just the one column to align. Any help or suggestions would be greatly appreciated! I am also using python 3.x
To note I am using tuples to contain all the information, with all_lines being the master list, as it were. The information is being read from a csv originally. Apologies for the horrible naming conventions, trying to work on functionality first.
Sorry if this has been answered elsewhere; I have tried looking.
EDIT: Here is the code im using for my all_lines
import csv
open_file = open('items.csv', 'r+')
all_lines = []
for line in open_file:
splitline = line.strip().split(',')
all_lines.append((splitline[0], splitline[1], splitline[2], splitline[3]))
And here is the csv file information:
Rusty Bucket,40L bucket - quite rusty,0.0,in
Golf Cart,Tesla powered 250 turbo,195.0,out
Thermomix,TM-31,25.5,out
AeroPress,Great coffee maker,5.0,in
Guitar,JTV-59,12.95,in
You should look at str.ljust(width[, fillchar]):
> '(TM-31)'.ljust(15)
'(TM-31) ' # pad to width
Then extract the variable-length {} ({}) part and padd it to the necessary width.
What you are looking for may be:
[EDIT] I have now also included a tabulate version since you may gain flexibility with this.
import csv
from tabulate import tabulate
open_file = open('items.csv', 'r+')
all_lines = []
for line in open_file:
splitline = line.strip().split(',')
all_lines.append((splitline[0], splitline[1], splitline[2], splitline[3]))
#print all_lines
count = 0
new_lines=[]
for splitline in all_lines:
in_out = splitline[3]
dollar_sign = "= $"
daily_price = "{0:.2f}".format(float(splitline[2]))
if in_out == "out":
in_out = str("*")
else:
in_out = str("")
str2='('+splitline[1]+')'
print count, "- {:<30} {:<30} {}{:<30} {:<10}".format(splitline[0], str2, dollar_sign, daily_price, in_out)
new_lines.append([splitline[0], str2, dollar_sign, daily_price, in_out])
count += 1
print tabulate(new_lines, tablefmt="plain")
print
print tabulate(new_lines, tablefmt="plain", numalign="left")
I do not like the idea of controlling printing format myself.
In this case, I would leverage a tabulating library such as: Tabulate.
The two key points are:
keep data in a table (e.g. list in a list)
select proper printing format with tablefmt param.
I am trying to get my output data to look like this:
-------------------------------------------------------
Grade Report for Programs
-------------------------------------------------------
Jacobson, Mark 19.0 <--- 20,17,20
Snurd, Mortimur 16.5 <--- 20,19,18,17,16,15,14,13
Luxemburg, Rosa 15.0 <--- 18,15,20,10,12
Atanasoff, John 20.0 <--- 20,20,20,20,20,20,20
Hopper, Grace 20.0 <--- 20,20,20,20,20,20
-------------------------------------------------------
But I don't know how to deal with the varying name length. My output currently looks like this.
Grade Report for Programs
-------------------------------------------------------
Jacobson, Mark 19.0 <--- 20,17,20
Snurd, Mortimur 16.5 <--- 20,19,18,17,16,15,14,13
Luxemburg, Rosa 15.0 <--- 18,15,20,10,12
Atanasoff, John 20.0 <--- 20,20,20,20,20,20,20
Hopper, Grace 20.0 <--- 20,20,20,20,20,20
-------------------------------------------------------
The program I have written is to take an input file of grade scores and collect the data and neatly print out the average.
The input file looks something like this:
Mark Jacobson,20,17,20
Mortimur Snurd,20,19,18,17,16,15,14,13
Rosa Luxemburg,18,15,20,10,12
John Atanasoff,20,20,20,20,20,20,20
Grace Hopper,20,20,20,20,20,20
And here is my code that collects the name and scores, and prints out the data with last name, first name, average score, then the actual scores that resulted to the average.
file = input("Enter filename: ")
grade_file = open(file, 'r')
print()
print('---------------------------------------------------------')
print('\t\tGrade Report for Programs')
print('---------------------------------------------------------')
for text in grade_file:
end_of_name = text.find(',')
name_seperated = text.find(' ')
first_name = text[0:name_seperated]
last_name = text[name_seperated+1:end_of_name]
name_last_first = last_name + "," + " " + first_name
grades = text[end_of_name+1:]
start = 0
index = 0
sum_n = 0
average= 0
score = 0
count = 0
while index < len(grades):
if grades[index] == ',':
score = int(grades[start:index])
count += 1
sum_n = score + sum_n
start = index + 1
index += 1
count += 1
score = int(grades[start:index])
sum_n = score + sum_n
average = sum_n / count
print(name_last_first, " ", average, "<---", grades)
print('---------------------------------------------------------')
grade_file.close()
I just need to figure out how to have even spaces so it makes an even row and column like the first output. Help is greatly appreciated! Thanks!
One way is to use Python's builtin C-style formatting. Note that a negative field width indicates that the field is to be left-justified:
>>> print("%-30s %4.1f" % ("Jacobson, Mark", 19.0))
Jacobson, Mark 19.0
>>>
Alternatively, you can use the string format method:
>>> print("{:30s} {:4.1f}".format("Jacobson, Mark", 19.0))
Jacobson, Mark 19.0
>>>
You can also use Formatted String Literals (f-strings):
>>> name = "Jacobson, Mark"
>>> average = 19.0
>>> print(f"{name:30s} {average:4.1f}")
Jacobson, Mark 19.0
>>>
Use string formatting with field width specifiers:
print('{:20s} {:4.1f} <--- {}'.format(name_last_first, average, grades))
This uses the str.format() method with the Format String Syntax to slot values into a template.
The first slot formats strings into a field 20 characters wide, the second slots floating point numbers into a field 4 characters wide, using 1 digit after the decimal point (leaving 1 for the decimal point itself plus 2 digits before the point).
If I were you, I'd also look at the csv module to read your data, rather than use string manipulations. You'll get list objects with separate values for each column:
import csv
print('---------------------------------------------------------')
print('\t\tGrade Report for Programs')
print('---------------------------------------------------------')
with open(file, 'r', newline='') as grade_file:
reader = csv.reader(grade_file)
for row in reader:
name = row[0]
name = ' '.join(map(str.strip, reversed(name.split(',')))
grades = [int(g) for g in row[1:])
average = sum(grades) / len(grades)
print('{:20s} {:4.1f} <--- {}'.format(name, average, ','.join(grades)))
print('---------------------------------------------------------')
The answer I find easiest is just using some basic string arithmetic.
For example, say for want the aligned a variable 20 spaces ahead of left-alignment, in your case the "average" variable, you could simply do this
print(name_last_first + (' ' * (20-len(name_last_first))) + average
+ "<----" + grades)
It's just a bit lengthier, but the code is easier to interpret in my opinion.
(Note: this method only works with mono spaced fonts! But most Python output is defaulted to a MS font :-) )
You can use this code :
handle = open('grade.txt')
name= list()
avg = list()
scores = list()
for line in handle:
line = line.strip()
spos = line.find(',')
scores.append(line[spos+1:])
words = line.split(',')
words = words
name.append(words[0])
add = 0
for i in range(1,len(words)):
add = add+int(words[i])
average = add/(len(words)-1)
avg.append(average)
for i in range(len(avg)):
tname = name[i].split()
fname = tname[0]
sname = tname[1]
order = sname+', '+fname
print("%-20s %-3.1f <--- %-30s " %(order,float(avg[i]),scores[i]))
The final line is for displaying it in an organized manner, you're code was lacking it only.
I know it was asked already but the answers the super unclear
The first requirement is to open a file (sadly I have no idea how to do that)
The second requirement is a section of code that does the following:
Each line represents a single student and consists of a student number, a name, a section code and a midterm grade, all separated by whitespace
So I don't think i can target that element due to it being separate by whitespace?
Here is an excerpt of the file, showing line structure
987654322 Xu Carolyn L0101 19.5
233432555 Jones Billy Andrew L5101 16.0
555432345 Patel Amrit L0101 13.5
888332441 Fletcher Bobby L0201 18
777998713 Van Ryan Sarah Jane L5101 20
877633234 Zhang Peter L0102 9.5
543444555 Martin Joseph L0101 15
876543222 Abdolhosseini Mohammad Mazen L0102 18.5
I was provided the following hints:
Notice that the number of names per student varies.
Use rstrip() to get rid of extraneous whitespace at the end of the lines.
I don't understand the second hint.
This is what I have so far:
counter = 0
elements = -1
for sets in the_file
elements = elements + 1
if elements = 3
I know it has something to do with readlines() and the targeting the section code.
marks = [float(line.strip().split()[-1]) for line in open('path/to/input/file')]
average = sum(marks)/len(marks)
Hope this helps
Open and writing to files
strip method
Something like this?
data = {}
with open(filename) as f:#open a file
for line in f.readlines():#proceed through file lines
#next row is to split data using spaces and them skip empty using strip
stData = [x.strip() for x in line.split() if x.strip()]
#assign to variables
studentN, studentName, sectionCode, midtermGrade = stData
if sectionCode not in data:
data[sectionCode] = []
#building dict, key is a section code, value is a tuple with student info
data[sectionCode].append([studentN, studentName, float(midtermGrade)]
#make calculations
for k,v in data.iteritems():#iteritems returns you (key, value) pair on each iteration
print 'Section:' + k + ' Grade:' + str(sum(x[2] for x in v['grade']))
more or less:
infile = open('grade_file.txt', 'r')
score = 0
n = 0
for line in infile.readlines():
score += float(line.rstrip().split()[-1])
n += 1
avg = score / n