如何计算文本文件中班级成员的平均分数?

时间:2019-01-23 22:33:19

标签: python

对于我的python初学者课程,我得到了以下作业:

在输入文件中,列出了2b组的地理测试成绩。在圣诞节假期之前,已向学生提供的半年度报告中已经包含了三项考试的成绩。 在输入的每一行中,您都可以找到学生的姓名,然后是一个或多个分数(“ _”)。这些均以考试成绩为准,例如:

Anne Adema____________6.5 5.5 4.5
Bea de Bruin__________6.7 7.2 7.7
Chris Cohen___________6.8 7.8 7.3
Dirk Dirksen__________1.0 5.0 7.7

可能的最低分数为1,最高分数为10。如果某人未通过考试,则列表中的分数为1。 您的任务是为第2b组的地理课程制作报告,该报告应如下所示:

Report for group 2b

Anne Adema has an average grade of 5.5
Bea de Bruin has an average grade of 7.2
Chris Cohen has an average grade of 7.3
Dirk Dirksen has an average grade of 4.6

End of report

到目前为止,这是我的python代码:

NUMBER_OF_GRADES = 3

file =open('grades1.in.txt').read().split('\n')
for scores in file:
    name_numbers = (scores.split('_'))

def averages ():
    for numbers in file:
        sum=0
        numbers = split("\n")
        for num in numbers:
            sum = sum + int(num)
        averages = sum/NUMBER_OF_GRADES
    print ('% has an average grade of %.1') %(name, averages)

哪里出错了?我想念什么?我不是以正确的方式分裂吗?

4 个答案:

答案 0 :(得分:0)

首先,您根本没有调用函数averages。您应该将其添加为代码的最后一行,但实际上根本不需要功能定义。

  • 使用with语句打开并自动关闭文件。
  • 接下来,您可以使用re包在下划线处分割行。
  • 您必须拆分成绩列表(假设它们由空格分隔)
  • 您可以使用内置功能sumlen计算成绩的总和和数量。

最后,它可能看起来像这样

import re

with open('grades1.in.txt') as grades_file:
    for line in grades_file:
        name, grades = re.split("_+", line)
        grades = [float(k) for k in grades.split()]
        avg = sum(grades)/len(grades)
        print("{} has an average grade of {:.2f}.".format(name, avg))

答案 1 :(得分:0)

GoTN已经回答了您的问题。

要弄清楚和改进一点,可以尝试:

def averages(line, number_of_grades):
    line_parsed = line.split('_')

    numbers = [float(x) for line_parsed[-1].split(' ')]

    name = line_parsed[0]

    # you can use number_of_grades or len(numbers)
    # Although, if the student only has 2 grades in the file,
    # but it was supposed to be two the average will be wrong.
    avg = sum(numbers)/number_of_grades

    print("{} has an average grade of {:.2f}.".format(name, avg))
    # or print(f'{name} has an average grade of {avg:.2f}')

NUMBER_OF_GRADES = 3

files =open('grades1.in.txt').read().splitlines()

for line in files:
    if len(line) > 0:
        averages(line, NUMBER_OF_GRADES)

答案 2 :(得分:0)

您的代码有些错误。也许应该将其迁移到Code Review,但是我现在将在这里写下答案。

我将尽可能使它与您的版本保持一致,以便您了解如何从自己的位置转到工作的示例,而无需大量可能尚未学习的知识。首先,让我们一次来看一下自己的一部分。

file =open('grades1.in.txt').read().split('\n')

您的file将是一个字符串列表,其中每个字符串都是输入文件中的一行。请注意,如果输入中包含空行,则此列表中的某些行将为空字符串。这一点以后很重要。

for scores in file:
    name_numbers = (scores.split('_'))

可以很好地将行的名称部分与行的分数部分分开,因此我们将其保留下来,但是您在这里做什么呢?现在,您正在用文件中的每一行覆盖name_numbers,并且从不对其进行任何操作,因此我们将把它移到您的函数中,并更好地利用它。

def averages():

没有参数?我们将为此工作。

    for numbers in file:

请记住,您的file是一个列表,列表中的每个条目都是输入文件的一行,因此,numbers in file并没有任何意义。我认为这是您首先要出错的地方。您想用scores.split('_')对它们进行分割后查看每一行中的数字,为此,我们需要对分割的结果进行索引。当您分割第一行时,您会得到类似的信息:

split_line = ['Anne Adema', '', '', '', '', '', '', '', '', '', '', '', '6.5 5.5 4.5']

第一个元素(split_line[0])是名称,最后一个元素(split_line[-1])是数字,但是您仍然必须将那些分开!要获取数字列表,您实际上必须将其拆分,然后将每个字符串解释为数字。您可以像这样通过列表理解(在Python中循环的最佳方法)很容易地做到这一点:

numbers = [float(n) for n in split_line[-1].split(' ')]

内容类似:首先在空格处将行的最后一个元素分割成['6.5', '5.5', '4.5'](注意它们都是 strings ),然后将该列表中的每个值转换为一个浮点数,最后将此浮点列表另存为numbers。好,继续:

        sum=0
        numbers = split("\n")  # already talked about this
        for num in numbers:
            sum = sum + int(num)
        averages = sum/NUMBER_OF_GRADES

sum是Python中的关键字,我们从不希望为关键字分配任何内容,因此此处存在错误。实际上,您可以仅在任何列表(实际上是任何可迭代的)sum(my_list)上调用my_list来获取列表中所有值的总和。要求平均值,您只想将该总和除以列表的 length ,您可以使用len(my_list)得到它。

    print ('% has an average grade of %.1') %(name, averages)

有一些很酷的更新方法可以打印带格式的文本,我将在下面显示其中一种,但是如果您应该使用这种方式,那么我会坚持使用。就是说,我无法让这条线为我服务,所以我选择了我更了解的东西。


将其重写为有效的内容:

def averages(line):
    if line is '':
        return  # skips blank lines!
    name_numbers = line.split('_')  # now we split our line
    name = name_numbers[0]
    numbers = [float(n) for n in name_numbers[-1].split(' ')]
    average = sum(numbers) / len(numbers)
    print('{} has an average grade of {:.2}'.format(name, average))

并在您的数据上运行它:

file =open('grades1.in.txt').read().split('\n')
for line in file:
    averages(line)  # call the function on each line
# Anne Adema has an average grade of 5.5
# Bea de Bruin has an average grade of 7.2
# Chris Cohen has an average grade of 7.3
# Dirk Dirksen has an average grade of 4.6

函数调用下方的注释中显示了结果。还有一点需要注意,您永远不会关闭文件,实际上,您永远不会保存文件句柄来关闭它。通过使用Python中的context manager语法,您可以摆脱任何麻烦:

with open('grades1.in.txt', 'r') as a_file:
    for line in a_file:
        averages(line)

这将自动处理关闭文件,如果在上下文管理器中执行的代码块中间遇到错误,甚至可以确保关闭文件。您可以遍历a_file,因为它基本上是一个可迭代的函数,每次访问文件时都会返回文件的下一行。

答案 3 :(得分:0)

将行拆分为 有点复杂。下面的代码通过首先用空格替换所有get_the_title_with_span字符,然后拆分 that 的结果来实现此目的。由于全名可能有可变数量的部分,因此使用负索引对这种分割的结果进行“切片”,该索引在值序列的末尾向后退计数。

这是通过利用以下事实而起作用的:我们知道最后三个项目必须是测试成绩,因此,它们之前的所有内容都必须是组成名称的部分。这是这样做的行:

"_"

这是完整的代码:

names, test_scores = line[:-NUMBER_OF_GRADES], line[-NUMBER_OF_GRADES:]

输出:

NUMBER_OF_GRADES = 3

with open('grades1.in.txt') as file:
    for line in file:
        line = line.replace('_', ' ').split()
        names, test_scores = line[:-NUMBER_OF_GRADES], line[-NUMBER_OF_GRADES:]
        name = ' '.join(names)  # Join names together.
        test_scores = [float(score) for score in test_scores]  # Make numeric.
        average_score = sum(test_scores) / len(test_scores)
        print('%s has an average grade of %.1f' % (name, average_score))