Perl:仅打印列表中的重复值

时间:2012-05-31 06:20:44

标签: perl list

使用Perl,我想只打印每个列表中的重复(重复)值。值应至少出现2次(2次或更多次)。每个列表(行)应单独考虑。

例如,给定输入:

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;

有人可以指导我对代码需要进行哪些更改? 谢谢!

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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;,并最好将-w替换为use warnings;以便移植。无论如何,当你要逐行处理它时,也没有必要啜饮你的文件。

答案 2 :(得分: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";
}