Есть ли простой способ проверить хэш сравнения элементов хеша? - PullRequest
1 голос
/ 22 ноября 2011

Есть ли простой способ проверки хеша сравнения хеш-элемента?

Мне нужно проверить хэш-элемент Perl хеш-элемента $ Table {$ key1} {$ key2} {K1} {Value} сравнитько всем остальным элементам в хэше

третий ключ будет от k1 до kn, и я хочу сравнить эти элементы, а остальные ключи такие же

if ($Table{$key1}{$key2}{K1}{Value} eq $Table{$key1}{$key2}{K2}{Value}
    eq  $Table{$key1}{$key2}{K3}{Value} ) 
{
   #do whatever
}

Ответы [ 4 ]

2 голосов
/ 22 ноября 2011

Примерно так может работать:

use List::MoreUtils 'all';

my @keys = map "K$_", 1..10;

print "All keys equal"
    if all { $Table{$key1}{$key2}{$keys[1]}{Value} eq $Table{$key1}{$key2}{$_}{Value} } @keys;
1 голос
/ 22 ноября 2011

Я бы использовал Data::Dumper, чтобы помочь с такой задачей, особенно для более общей проблемы (где третий ключ более произвольный, чем 'K1' ... 'Kn'). Используйте Data::Dumper, чтобы структурировать структуры данных, а затем сравнить строки.

use Data::Dumper;

# this line is needed to assure that hashes with the same keys output
# those keys in the same order.
$Data::Dumper::Sortkeys = 1;

my $string1= Data::Dumper->Dump($Table{$key1}{$key2}{k1});

for ($n=2; exists($Table{$key1}{$key2}{"k$n"}; $n++) {

    my $string_n = Data::Dumper->Dump($Table{$key1}{$key2}{"k$n"});

    if ($string1 ne $string_n) {
        warn "key 'k$n' is different from 'k1'";
    }

}

Это можно использовать для более общего случая, когда $Table{$key1}{$key2}{k7}{value} сам содержит сложную структуру данных. Однако, когда обнаружена разница, это не поможет вам выяснить, где эта разница.

0 голосов
/ 22 ноября 2011

Довольно сложная структура.Вы должны изучить использование методов объектно-ориентированного программирования .Это значительно упростит ваше программирование и обработку этих сложных структур.

Прежде всего, давайте немного упростим.Когда вы говорите:

$Table{$key1}{$key2}{k1}{value}

Вы действительно имеете в виду:

my $value = $Table{$key1}->{$key2}->{k1};

или

my $actual_value = $Table{$key1}->{$key2}->{k1}->{Value};

Я собираюсь предположить первый.Если я не прав, дайте мне знать, и я обновлю свой ответ.

Давайте упростим:

my %hash = %{$Table{$key1}->{$key2}};

Теперь мы имеем дело с хэшем.Вы можете использовать два метода:

  1. Сортировать ключи этого хэша по значению, тогда, если два ключа имеют одинаковое значение, они будут рядом друг с другом в отсортированном списке, что упрощаетобнаруживать дубликаты.Преимущество состоит в том, что все дубликаты ключей будут напечатаны вместе.Недостатком является то, что это сортировка, которая требует времени и ресурсов.
  2. Обратный хэш, поэтому он определяется по значению, а значение этого ключа является ключом.Если ключ уже существует, мы знаем, что другой ключ имеет повторяющееся значение.Это быстрее, чем первый метод, потому что сортировка не производится.Однако дубликаты будут обнаружены, но не распечатаны вместе.

Вот первый метод:

my %hash = %{$Table{$key1}->{$key2}};
my $previous_value;
my $previous_key;
foreach my $key (sort {$hash{$a} cmp $hash{$b}} keys %hash) {
    if (defined $previous_key and $previous_value eq $hash{$key}) {
        print "\$hash{$key} is a duplicate of \$hash{$previous_key}\n";
    }
    $previous_value = $hash{$key};
    $previous_key = $key;   
}

И второй:

my %hash = %{$Table{$key1}->{$key2}};
my %reverse_hash;
foreach $key (keys %hash) {
   my $value = $hash{$key};
   if (exists $reverse_hash{$value}) {
       print "\$hash{$reverse_hash{$value}} has the same value as \$hash{$key}\n";
   }
   else {
       $reverse_hash{$value} = $key;
   }
}
0 голосов
/ 22 ноября 2011

Альтернативный подход к проблеме - это сделать функцию утилиты, которая будет сравнивать все ключи, если одинаковое значение, возвращаемое некоторой функцией для всех клавиш:

sub AllSame (&\%) {
  my ($c, $h) = @_;
  my @k = keys %$h;
  my $ref;
  $ref = $c->() for $h->{shift @k};
  $ref ne $c->() and return for @$h{@k};
  return 1
}

print "OK\n" if AllSame {$_->{Value}} %{$Table{$key1}{$key2}};

Но если вы начнете думать таким образом, вы можете найти этоподход гораздо более общий ( рекомендуемый способ ):

sub AllSame (@) {
  my $ref = shift;
  $ref ne $_ and return for @_;
  return 1
}

print "OK\n" if AllSame map {$_->{Value}} values %{$Table{$key1}{$key2}};

Если операция отображения стоит дорого, вы можете сделать ленивый аналог того же:

sub AllSameMap (&@) {
  my $c = shift;
  my $ref;
  $ref = $c->() for shift;
  $ref ne $c->() and return for @_;
  return 1
}

print "OK\n" if AllSameMap {$_->{Value}} values %{$Table{$key1}{$key2}};

Если вы хотите тольконекоторые подмножества ключей, которые вы можете использовать синтаксис среза хеша, например:

print "OK\n" if AllSame map {$_->{Value}} @{$Table{$key1}{$key2}}{map "K$_", 1..10};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...