Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Evenly space output data with varying string lengths

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!

like image 417
Alik Avatar asked Oct 24 '15 21:10

Alik


2 Answers

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
>>> 
like image 55
Tom Karzes Avatar answered Sep 18 '22 01:09

Tom Karzes


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('---------------------------------------------------------')
like image 42
Martijn Pieters Avatar answered Sep 20 '22 01:09

Martijn Pieters