2013-04-13 63 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