简体   繁体   中英

Reading floats from a file Python

My input file consists of a bunch of names and grades, example:

Leo DiCaprio______4.5 6.5 7.5
Sean Connery______ 3.5 8.5 5.5
[...]

I've tried all the ways I can think of but always get the same problem, Cant convert str to float for the grades. the goal is to calculate the average grade for every person.

def average_grade(filename):
infile = open(filename, 'r')
floats = []
names = []
for line in infile:
    words = line.split('_')
    names.append(words[0])
    floats.append(float(words[1]))
infile.close()

print(names)


'''Start'''
average_grade('grades1.txt')

You are quite off the mark here.

Your line contains more than a single underscore _ character. The split result will be the following:

>>> line = 'Leo DiCaprio______4.5 6.5 7.5\n' #\n added to simulate a line read from a file.
>>> line.split('_')
['Leo DiCaprio', '', '', '', '', '', '4.5 6.5 7.5\n']

To access the "floats" you need to take the last item of the split result.

>>> floats = line.split('_')[-1].strip() #strip out the '\n'
>>> floats
'4.5 6.5 7.5'

Note however that you have multiple numbers here, separated by a space. You cannot convert to float all at once, you need to split them again.

The following line will split floats in the constituant items, then it converts them to actual float type.

>>> numbers = [float(x) for x in floats.split()]
>>> numbers
[4.5, 6.5, 7.5]

Now, I think you probably want to make a table out of the names and the numbers. The easiest way to do that is to use a dict.

Also, I reccomend to dont use floats as a variable name, you can easily confuse it with the float type. Find a better name. I am not sure what that numbers are, so I will just call it numbers in the following code, but you should choose a proper name for example scores or grades or whatever they actually are.

table = {}
with open('grades1.txt', 'r') as f: #use the with statement to open files!
    for line in f:
        words = line.strip().split('_')
        name = words[0]
        numbers = [float(x) for x in words[-1].split()]
        table[name] = numbers

for k,v in table.items():
    print(k, v)

you can use regex on your input file, to get the grades of each person, plus their name. So run a for loop on each line in the file, get the name of each person and their grades. Once you have got the grades you can split the string of the grades by space(or whatever separates them). This creates a list that you can work with and convert each string of the grades into float then you know how to calculate the average from there:)

Let me know if this worked out for you!

I could just give you the solution, but I want to help you understand what you do.

First, I change your code so that it works without a separate file.

That's not what you should do, but that helps me to have the code separate.

def average_grade(data):
    floats = []
    names = []
    for line in data:
        words = line.split('_')
        names.append(words[0])
        floats.append(float(words[1]))
    print(names)

average_grade('Leo DiCaprio______4.5 6.5 7.5', 'Sean Connery______ 3.5 8.5 5.5')

When I execute this code, I get ValueError: could not convert string to float: as well.

But why? Well, let's then change the code:

def average_grade(data):
    floats = []
    names = []
    for line in data:
        words = line.split('_')
        print(words)
        names.append(words[0])
        floats.append(float(words[1]))
    print(names)

average_grade('Leo DiCaprio______4.5 6.5 7.5', 'Sean Connery______ 3.5 8.5 5.5')

This print(words) gives us ['Leo DiCaprio', '', '', '', '', '', '4.5 6.5 7.5']

We see that our technique to split the lines is not very good yet.

Let's try harder:

def average_grade(*data):
    floats = []
    names = []
    for line in data:
        words = line.split('_', 1)
        name = words[0]
        cursor = len(name)
        while line[cursor] == '_':
            cursor += 1
        grades = line[cursor:]
        print((name, grades))
        grades = grades.split()
        print((name, grades))
        grades = [float(i) for i in grades]
        avg = sum(grades) / len(grades)
        print((name, grades, avg))
        names.append(name)
        # Now, what to do with these grades? Do we add them all to the list?
        floats.append(avg)
    print(names)
    print(floats)

average_grade('Leo DiCaprio______4.5 6.5 7.5', 'Sean Connery______ 3.5 8.5 5.5')

Now we see how the grades list evolves:

('Leo DiCaprio', '4.5 6.5 7.5') # this is our "original", after eliminating the `_`s.
('Leo DiCaprio', ['4.5', '6.5', '7.5']) # This is a list of the strings representung the grades
('Leo DiCaprio', [4.5, 6.5, 7.5], 6.166666666666667) # This is a list of the numbers, along with their average
('Sean Connery', ' 3.5 8.5 5.5') # from here on, the same for Sean
('Sean Connery', ['3.5', '8.5', '5.5'])
('Sean Connery', [3.5, 8.5, 5.5], 5.833333333333333)
['Leo DiCaprio', 'Sean Connery']
[6.166666666666667, 5.833333333333333]

I hope that helps a bit.

Note that the way how I split on the ____ part is a bit "manual"; it would surely better to use another technique such as regular expressions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM