Perl CSV删除仅出现一次的行

时间:2013-04-13 09:58:59

标签: perl csv

嗨专家和善良的帮助者,

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

我甚至不确定从哪里开始。非常感谢任何帮助/建议。

1 个答案:

答案 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);
  }
}