3

使用 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;

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

4

3 回答 3

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
于 2012-05-31T06:37:18.583 回答
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;并最好替换-wuse warnings;可移植性。无论如何,当您要逐行处理文件时,也没有必要啜饮您的文件。

于 2012-05-31T06:56:33.590 回答
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";
}
于 2012-05-31T06:50:15.640 回答