1

嗨专家和好心的助手,

我是 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

在上面的示例中,Mike 是唯一一个不与其他学生分享他的分数(第二列,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

我什至不知道从哪里开始。非常感谢任何帮助/建议。

4

1 回答 1

2

I would use a hash to associate the rows with the value of their second column. In the second step, I would filter out all keys who have only one associated row:

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
  }
}

However, you should actually use Text::CSV instead of split:

my $fh = \*DATA; # or open $fh to a file
while(my $row = $csv->getline($fh)) {
  push ...;
}

and

for my $key (@keys) {
  for my $row (@{ $rows{$key} }) {
    $csv->print(\*STDOUT, $row);
  }
}
于 2013-04-13T10:20:32.450 回答