2012-05-31 31 views
3

使用Perl,我只想在每個列表中打印重複(重複)值。這些值應至少出現2次(2次或更多次)。每個列表(行)應該分開考慮。Perl:只打印列表中重複的值

例如,給定輸入:

abc 51082 6457 31072 5575 5488 4842 16567 151 

cde 5575 3674 8150 5575 3674 8150 

fgh 5737 6887 48278 3674 34399 3674 8150 

我想下面的輸出:

abc 
cde 5575 3674 8150 
fgh 3674 

我寫了下面的源代碼,但它沒有給出正確的輸出:

#!/usr/bin/perl -w 

open FH, "input.txt"; 
@a=<FH>; 

my %count_of; 

foreach $tmp (@a) 
{ 
    foreach $word (split /\s/, $tmp) 
    { 
     $count_of{$word}++; 

     if ($count_of{$word} >=2) 
     { 
      print "$word\n"; 
     } 
    } 
} 

exit; 

有人請指導我需要對代碼進行哪些更改? 謝謝!

+1

你究竟發生了什麼錯誤? –

回答

1

這裏有一個工作版本。看看註釋代碼來了解更正

#!/usr/bin/perl 

# always use strict and warnings: this will help you to find errors 
use warnings; 
use strict; 

open FH, 'input.txt'; 

# always declare variables 
my @a=<FH>; 

# you should close file handles 
close FH; 

# declare $tmp 
foreach my $tmp (@a) { 

    # you need to process the first element differently since you 
    # want to always print it 
    my @row = split /\s/, $tmp; 

    # you should check for empty rows 
    if (@row == 0) { 
     # empty row 
     next; 
    } 

    # removes the first element 
    my $header = shift @row; 

    # the first element is always printed 
    print $header; 

    # this should be local otherwise you are counting globally 
    # a new declaration will give you a new hash 
    my %count_of; 

    # declare $word 
    foreach my $word (@row) { 

     # you should not increment an undefined variable 
     if ($count_of{$word}) { 
      $count_of{$word} = 1; 
     } else { 
      $count_of{$word}++; 
     } 

     # just print the second time you see the word 
     if ($count_of{$word} == 2) { 
      print " $word"; 
     } 

    } 

    print "\n"; 

} 

# it is good practice to return true at the end of a script (no need to exit) 
1; 

這將產生:

abc 
cde 5575 3674 8150 
fgh 3674 
+0

我不認爲這看起來很正確。如果有兩個以上的重複項,這個打印是否會重複?例如,如果有三個相同的號碼不會打印該號碼兩次? – mttrb

+0

@mttrb:更正 – Matteo

+0

看起來更好:) – mttrb

0
#!/usr/bin/perl -w 

use strict; 

while (<>) { 
    chomp; 
    my ($name, @inp) = split /\s+/ or next; 
    my %counts; 
    for (@inp) { $counts{$_}++ } 
    print join (' ', $name, map { $counts{$_} > 1 ? $_ :() } keys %counts), "\n"; 
} 
1

grep與保持看到值的軌道散列組合是非常適合這類問題:

#!/usr/bin/env perl 
use strict; 
use warnings; 

my $file = "input.txt"; 
open my $fh, "<", "$file" or die "Unable to open $file: $!\n"; 

while (<$fh>) { 
    chomp; 
    my ($key, @values) = split or next; # skip empty rows 
    my (%seen, @dupl); 
    @dupl = grep $seen{$_}++ == 1, @values; 
    print "$key @dupl\n"; 
} 

輸出:

abc 
cde 5575 3674 8150 
fgh 3674 

請注意,or(與||相對)在兩種情況下都至關重要。此外,您應該始終檢查您嘗試打開文件的結果,use strict;,最好用use warnings;替換-w以確保便攜性。無論如何,當你要逐行處理它時,也不必啜泣你的文件。

+0

如果輸入列表包含2個以上相等的值,則它們也將在輸出中進行復制。 – Alan

+0

@Alan:我想我只是打敗你。 ;) – flesk