嗨专家和善良的帮助者,
我是Perl的新手,我可以在这里使用一些帮助。我正在处理一个超过1000行的CSV文件,但我在这里复制并简化了我的问题。
基本上,我想根据天气或不重复的第二列删除一些行。我知道这可能听起来令人困惑,请允许我举例说明。
输入数据:
M,100,John,10
M,98,Mike,9
F,99,Amelia,9
F,100,Rosana,10
F,100,Susan,11
M,99,James,8
预期产出:
M,100,John,10
F,100,Rosana,10
F,100,Susan,11
F,99,Amelia,9
M,99,James,8
在上面的示例中,迈克是唯一一个不与其他学生分享他的分数(第二列,98)的人,因此,不应该打印他的名字。换句话说,如果特定条目的第二列中的值在任何其他条目中是唯一的/不重复的,则应该省略它。排序是可选的。
这是我到目前为止所拥有的。
use Text::CSV;
use strict;
my $csv = Text::CSV->new();
my $sheet;
while( <DATA> ) {
chomp;
my $row;
@$row = split( /,/, $_ );
push @$sheet, $row;
}
@$sheet = sort { $b->[1] <=> $a->[1] } @$sheet;
foreach my $row ( @$sheet ) {
print join( ',', @$row), "\n";
}
__DATA__
M,100,John,10
M,98,Mike,9
F,99,Amelia,9
F,100,Rosana,10
F,100,Susan,11
M,99,James,8
我甚至不确定从哪里开始。非常感谢任何帮助/建议。
答案 0 :(得分:2)
我会使用哈希将行与第二列的值相关联。在第二步中,我将过滤掉只有一个关联行的所有键:
my %rows;
while (...) {
...;
push @{ $rows{$row->[1]} }, $row;
}
# After the loop, we filter the keys (and sort them):
my @keys = sort {$b <=> $a} grep { @{$rows{$_}} > 1 } keys %rows;
# Then print them:
for my $key (@keys) {
for my $row (@{ $rows{$key} }) {
# print the @$row
}
}
但是,您实际上应该使用Text::CSV
而不是split
:
my $fh = \*DATA; # or open $fh to a file
while(my $row = $csv->getline($fh)) {
push ...;
}
和
for my $key (@keys) {
for my $row (@{ $rows{$key} }) {
$csv->print(\*STDOUT, $row);
}
}