Remove the newline character in a list read from a file

Question:

I have a simple program that takes an ID number and prints information for the person matching the ID. The information is stored in a .dat file, with one ID number per line.

The problem is that my program is also reading the newline character n from the file. I have tried the ‘name’.split() method, but this doesn’t seem to work for a list.

My program:

from time import localtime, strftime

files = open("grades.dat")
request = open("requests.dat", "w")
lists = files.readlines()
grades = []

for i in range(len(lists)):
    grades.append(lists[i].split(","))

cont = "y"

while cont == "y" or cont == "Y":
    answer = raw_input("Please enter the Student I.D. of whom you are looking: ")
    for i in range(len(grades)):
        if answer == grades[i][0]:
            print grades[i][1] + ", " + grades[i][2] + (" "*6) + grades[i][0] + (" "*6) + grades[i][3]
            time = strftime("%a, %b %d %Y %H:%M:%S", localtime())
            print time
            print "Exams - " + grades[i][11] + ", " + grades[i][12] + ", " + grades[i][13]
            print "Homework - " + grades[i][4] + ", " + grades[i][5] + ", " + grades[i][6] + ", " + grades[i][7] + ", " +grades[i][8] + ", " + grades[i][9] + ", " + grades[i][10]
            total = int(grades[i][4]) + int(grades[i][5]) + int(grades[i][6]) + int(grades[i][7]) + int(grades[i][8]) + int(grades[i][9]) + int(grades[i][10]) + int(grades[i][11]) + int(grades[i][12]) + int(grades[i][13])
            print "Total points earned - " + str(total)
            grade = float(total) / 550
            grade = grade * 100
            if grade >= 90:
                print "Grade: " + str(grade) + ", that is equal to an A."
            elif grade >= 80 and grade < 90:
                print "Grade: " + str('%.2f' %grade) + ", that is equal to a B."
            elif grade >= 70 and grade < 80:
                print "Grade: " + str('%.2f' %grade) + ", that is equal to a C."
            elif grade >= 60 and grade < 70:
                print "Grade: " + str('%.2f' %grade) + ", that is equal to a D."
            else:
                print "Grade: " + str('%.2f' %grade) + ", that is equal to an F."
            request.write(grades[i][0] + " " + grades[i][1] + ", " + grades [i][2] +
                          " " + time)
            request.write("n")


    print
    cont = raw_input("Would you like to search again? ")

if cont != "y" or cont != "Y":
    print "Goodbye."
Asked By: Python Newbie

||

Answers:

You can use the strip() function to remove trailing (and leading) whitespace; passing it an argument will let you specify which whitespace:

for i in range(len(lists)):
    grades.append(lists[i].strip('n'))

It looks like you can just simplify the whole block though, since if your file stores one ID per line grades is just lists with newlines stripped:

Before

lists = files.readlines()
grades = []

for i in range(len(lists)):
    grades.append(lists[i].split(","))

After

grades = [x.strip() for x in files.readlines()]

(the above is a list comprehension)


Finally, you can loop over a list directly, instead of using an index:

Before

for i in range(len(grades)):
    # do something with grades[i]

After

for thisGrade in grades:
    # do something with thisGrade
Answered By: Michael Mrozek

You want the String.strip(s[, chars]) function, which will strip out whitespace characters or whatever characters (such as ‘n’) you specify in the chars argument.

See http://docs.python.org/release/2.3/lib/module-string.html

Answered By: DGH

str.strip() returns a string with leading+trailing whitespace removed, .lstrip and .rstrip for only leading and trailing respectively.

grades.append(lists[i].rstrip('n').split(','))
Answered By: ephemient

Here are various optimisations and applications of proper Python style to make your code a lot neater. I’ve put in some optional code using the csv module, which is more desirable than parsing it manually. I’ve also put in a bit of namedtuple goodness, but I don’t use the attributes that then provides. Names of the parts of the namedtuple are inaccurate, you’ll need to correct them.

import csv
from collections import namedtuple
from time import localtime, strftime

# Method one, reading the file into lists manually (less desirable)
with open('grades.dat') as files:
    grades = [[e.strip() for e in s.split(',')] for s in files]

# Method two, using csv and namedtuple
StudentRecord = namedtuple('StudentRecord', 'id, lastname, firstname, something, homework1, homework2, homework3, homework4, homework5, homework6, homework7, exam1, exam2, exam3')
grades = map(StudentRecord._make, csv.reader(open('grades.dat')))
# Now you could have student.id, student.lastname, etc.
# Skipping the namedtuple, you could do grades = map(tuple, csv.reader(open('grades.dat')))

request = open('requests.dat', 'w')
cont = 'y'

while cont.lower() == 'y':
    answer = raw_input('Please enter the Student I.D. of whom you are looking: ')
    for student in grades:
        if answer == student[0]:
            print '%s, %s      %s      %s' % (student[1], student[2], student[0], student[3])
            time = strftime('%a, %b %d %Y %H:%M:%S', localtime())
            print time
            print 'Exams - %s, %s, %s' % student[11:14]
            print 'Homework - %s, %s, %s, %s, %s, %s, %s' % student[4:11]
            total = sum(int(x) for x in student[4:14])
            print 'Total points earned - %d' % total
            grade = total / 5.5
            if grade >= 90:
                letter = 'an A'
            elif grade >= 80:
                letter = 'a B'
            elif grade >= 70:
                letter = 'a C'
            elif grade >= 60:
                letter = 'a D'
            else:
                letter = 'an F'

            if letter = 'an A':
                print 'Grade: %s, that is equal to %s.' % (grade, letter)
            else:
                print 'Grade: %.2f, that is equal to %s.' % (grade, letter)

            request.write('%s %s, %s %sn' % (student[0], student[1], student[2], time))


    print
    cont = raw_input('Would you like to search again? ')

print 'Goodbye.'
Answered By: Chris Morgan

You could actually put the newlines to good use by reading the entire file into memory as a single long string and then use them to split that into the list of grades by using the string splitlines() method which, by default, removes them in the process.

with open("grades.dat") as file:
    grades = [line.split(",") for line in file.read().splitlines()]
...
Answered By: martineau
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.