Как найти и посчитать повторяющиеся значения в хэше perl - PullRequest
4 голосов
/ 10 июня 2011

Мне нужно найти повторяющиеся значения в хэше perl, а затем вывести пару ключ / значение и соответствующий счетчик дубликатов, когда это число> 1.

(Я мог бы оставить пример кода того, что я пытался, но это привело бы к массовому замешательству и, возможно, неконтролируемому смеху, и я действительно надеюсь сделать это через жизнь с некоторым подобием самоуважения.) *

Ключ / значение хеша будет выглядеть следующим образом:

%hash = qw('FHDJ-124H' => 'hostname1', 'HJDHUR-87878' => 'hostname2', 'HGHDJH-874673' => 'hostname1');

Мой желаемый результат будет:

2 duplicates found for hostname1
    FHDJ-124H
    HGHDJH-874673

Использование perl 5.6 в Solaris 10. Строго контролируемая производственная среда, где обновление или загрузка perl-модов не допускается. (Запрос на изменение для перехода на 5.8 составляет около 6 месяцев).

Большое спасибо!

Ответы [ 4 ]

6 голосов
/ 10 июня 2011

Вам нужно перебирать ключи хеша в первом хеше (ключ / значение) и накапливать счетчик каждого элемента, который вы найдете в другом хеше (значение / количество).

Если вы хотите отобразитьключи вместе с дублированными значениями, ваш второй хэш не может быть таким простым, поскольку для каждого дублированного значения у вас будет набор ключей (все они имеют одинаковое значение).В этом случае просто накапливайте ключ в массиве, а затем считайте его элементы.Т.е. ваш второй хеш будет выглядеть примерно так (значение / [key1, key2, key3 ...])

my %hash = ( key1 => "one", key2 => "two", key3 => "one", key4 => "two", key5 => "one" );
my %counts = ();
foreach my $key (sort keys %hash) {
    my $value = $hash{$key}; 
    if (not exists $counts{$value}) {
        $counts{$value} = [];
    }
    push $counts{$value}, $key;
};

Затем итерируйте по $ count, чтобы вывести то, что вам нужно, когда количество элементов в $ count{$ value}> 1

4 голосов
/ 10 июня 2011

Это то, что вы ищете

#!/usr/bin/perl
use strict;
use warnings;
my %hash = ('FHDJ-124H' => 'hostname1', 'HJDHUR-87878' => 'hostname2', 'HGHDJH-874673' => 'hostname1');
my %reverse;

while (my ($key, $value) = each %hash) {
    push @{$reverse{$value}}, $key;
}

while (my ($key, $value) = each %reverse) {
    next unless @$value > 1;

    print scalar(@$value), " duplicates found \n @$value have the same key $key\n";     

}
2 голосов
/ 10 июня 2011

А как же:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dump qw(dump);

my %h = (a=>'v1', b=>'v2', c=>'v1', d=>'v3', e=>'v3');
my %r;
while(my($k,$v)=each%h){
    push @{$r{$v}}, {$k=>$v};
}
dump %r;

выход:

(
  "v1",
  [{ c => "v1" }, { a => "v1" }],
  "v2",
  [{ b => "v2" }],
  "v3",
  [{ e => "v3" }, { d => "v3" }],
)
1 голос
/ 10 июня 2011

Ну, в общем, вы могли бы сделать что-то вроде этого:

my @values=sort(values(%hash));
my @doubles=();
my %counts=();



foreach my $i (0..$#values)
{
    foreach my $j (($i+1)..$#values)
    {
        if($values[$i] eq $values[$j])
        {
            push @doubles,$values[$i];
            $counts{$values[$i]}++;

        }
    }
}

foreach(@doubles)
{
    print "$hash{$_}, $_, $counts{$_}\n";
}

Это немного наивное решение (которое я еще не тестировал), и я уверен, что есть более быстрый и приятный способ, но это должно сработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...