2013-04-13 62 views
1

嗨专家和亲切助手,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 

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

回答

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); 
    } 
} 
+0

这是现货!非常感谢,正是我所期待的:) – Yoboy

+0

你真了不起!再次感谢! :d – Yoboy