2012-05-31 2 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; и предпочтительно заменить -w на use warnings; для переносимости. Кроме того, нет необходимости обрабатывать ваш файл, когда вы будете обрабатывать его по очереди в любом случае.

+0

Если список ввода содержит более двух равных значений, они также будут дублироваться на выходе. – Alan

+0

@Alan: Думаю, я просто избил тебя. ;) – flesk

Смежные вопросы