【发布时间】:2020-01-30 17:21:50
【问题描述】:
我有 grades.tsv 文件,其中包含三列显示学生姓名、科目和成绩:
Liam Mathematics 5
Liam History 6
Liam Geography 8
Liam English 8
Aria Mathematics 8
Aria History 7
Aria Geography 6
Isabella Mathematics 9
Isabella History 4
Isabella Geography 7
Isabella English 5
Isabella Music 8
我想计算每个学生的平均成绩并将其添加到单独的列中。为此,我使用了两个文件句柄 DATA 和 OUT 打开同一个文件:
use strict;
use warnings;
# Open file with grades for calculation of average grade for each student
open (DATA,"grades.tsv") or die "Cannot open file\n";
my %grade_sums;
my %num_of_subjects;
# Calculate sum of grades and number of subjects for each student
while( <DATA> ) {
chomp;
my ($name, $subject, $grade) = split /\t/;
$grade_sums{$name} += $grade;
$num_of_subjects{$name} += 1;
}
close DATA;
# Open file with grades again but this time for a purpose of adding a separate column with average grade and printing a result
open (OUT,"grades.tsv") or die "Cannot open file\n";
while ( <OUT> ) {
chomp;
my ($name, $subject, $grade) = split /\t/;
# Calculate average grade
my $average_grade = $grade_sums{$name} / $num_of_subjects{$name};
my $outline = join("\t", $name, $subject, $grade, $average_grade);
# Print a file content with new column
print "$outline\n";
}
close OUT;
代码有效,但我不确定它是否适合这项任务。这是一种好的做法还是应该首选更好的方法?
【问题讨论】:
-
你不应该使用名称DATA,它是special package handle。
-
你应该使用三参数 open() 和词法文件句柄:
open my $data, '<', 'grades.tsv' or die ...; while (my $line = <$data>) { ... } -
我能看到的唯一危险——如果你的代码不能正常工作,你会覆盖原始文件(丢失它的内容,保留备份副本)。为什么不为每个学生创建一个带有摘要的新文件?
student number_of_subjects_taken average_mark -
我还要提一下 split \t 和 join \t 不足以处理 TSV 文件。见thomasburette.com/blog/2014/05/25/…。考虑Text::CSV
标签: perl filehandle