Как передать многоуровневую хеш-таблицу в perl

Я полностью застрял в проблеме:

У меня есть несколько огромных Perl-скриптов с несколькими огромными многоуровневыми хэш-таблицами. Все работает нормально, но для уменьшения кода и читабельности я хотел бы передать последнюю ссылку на хэш подфункции.

Как упоминалось ранее, у меня есть несколько разных хэш-таблиц, например. %hash_table1 и %hash_table2 имеют одинаковые значения, но разные уровни ключей.

hash_table1 с 3 уровнями ключей:

$hash_table1{$key1}{$key2}{$key3}->{value1}
$hash_table1{$key1}{$key2}{$key3}->{value2}
$hash_table1{$key1}{$key2}{$key3}->{value3}

У меня есть те же «значения» в другой хеш_таблице, но с другим многоуровневым: хэш_таблица2 с 2 уровнями ключей:

$hash_table2{$key1}{$key2}->{value1}
$hash_table2{$key1}{$key2}->{value2}
$hash_table2{$key1}{$key2}->{value3}

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

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

sub print_all_values {
    my %hash_tmp = shift @_;
    printf $hash_tmp->{value1}.";";
    printf $hash_tmp->{value2}.";";
    printf $hash_tmp->{value3}."\n";
}

и где-то в коде я обрабатываю многоуровневую обработку и просто передаю последнюю ссылку на предыдущую определенную подфункцию, чтобы сделать ... ну, что нужно делать там с сохраненными значениями (скажем, просто печать):

foreach my $k1 (sort {$a <=> $b} keys %hash_table1){
   foreach my $k2 (sort {$a <=> $b} keys %{$hash_table1{$k1}}){
      foreach my $k3 (sort {$a <=> $b} keys %{$hash_table1{$k1}{$k2}}
         print_all_values(%{$hash_table1{$k1}{$k2}{$k3}});
      }
   }
}

закончите где-нибудь еще код для доступа к двухуровневой хеш-таблице:

foreach my $k1 (sort {$a <=> $b} keys %hash_table2){
   foreach my $k2 (sort {$a <=> $b} keys %{$hash_table2{$k1}}){
      print_all_values(%{$hash_table2{$k1}{$k2}});
   }
}

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

Заранее большое спасибо за любой полезный комментарий,

всего наилучшего,

OldMcFunsy


person user2588230    schedule 16.07.2013    source источник
comment
Ой! От этого у меня болит мозг. Это решение требует объектно-ориентированного подхода. Это поможет синхронизировать все ваши хеш-ключи. Дайте мне немного больше информации о том, что представляют собой различные ключи, и я, возможно, смогу дать быстрый ответ. Объектно-ориентированный подход поможет вам справиться с этой кучей ключей и хеш-уровней, а ваш код будет намного чище и проще в обслуживании.   -  person David W.    schedule 16.07.2013
comment
%hash_tmp и $hash_tmp->{key} не относятся к одному и тому же хешу!   -  person mob    schedule 16.07.2013


Ответы (4)


Взгляните на perlref.

Вы должны просто передать ссылку на подпрограмму:

print_all_values(\%hash_table);

sub print_all_values {
    my $hash_tmp = shift;
    printf $hash_tmp->{value1}.";";
    printf $hash_tmp->{value2}.";";
    printf $hash_tmp->{value3}."\n";
}
person kjprice    schedule 16.07.2013
comment
Большое спасибо, я бы никогда не подумал об объявлении моего hash_tmp как ссылки, а не как hash_table. только что изменился с % на $. Вы не представляете, сколько часов я провел, пытаясь заставить этот код работать. Огромное спасибо!!! - person user2588230; 16.07.2013

sub print_all_values {
    print(join(";", @_), "\n");
}

for my $k1 (sort {$a <=> $b} keys %hash_table1) {
   for my $k2 (sort {$a <=> $b} keys %{ $hash_table1{$k1} }) {
      print_all_values(
         @{ $hash_table1{$k1}{$k2} }{
            sort {$a <=> $b} keys %{ $hash_table1{$k1}{$k2} }
         }
      );
   }
}

Извините, нет времени на объяснения.

person ikegami    schedule 16.07.2013
comment
Привет, спасибо вам обоим, оба решения работают и удовлетворяют мои требования. Вы не представляете, сколько часов я потратил на решение проблемы!!! - person user2588230; 16.07.2013

sub print_all_values {
    my %hash_tmp = shift @_;
    printf $hash_tmp->{value1}.";";
    printf $hash_tmp->{value2}.";";
    printf $hash_tmp->{value3}."\n";
}

$hash_tmp->{value1} ссылается на что-то совершенно отличное от %hash_tmp. Изменение их на $hash_tmp{value1}, вероятно, решит проблему. Кроме того, всегда используйте строгие и предупреждения.

person AKHolland    schedule 16.07.2013

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

# --------------------------------------
#       Name: scan_hash
#      Usage: %value_of = scan_hash( \%hash_tree, @keys );
#    Purpose: To do a depth first scan of the hash tree
#             and create a hash of the leaves.
# Parameters: \%hash_tree -- Tree to scan
#                   @keys -- List of keys; these may appear anywhere in the tree
#    Returns:   %value_of -- a simple key=>value has,
#                            the keys are from @keys
#                            and their values are what was found
#
sub scan_hash {
  my $hash_tree = shift @_;
  my @keys      = @_;
  my %value_of  = ();

  for my $key ( keys %$hash_tree ){

    # save if the current key is one we're looking for
    if( grep { $_ eq $key } @keys ){
      $value_of{$key} = $hash_tree->{$key};

    # is it a reference?
    }elsif( my $ref = ref( $hash_tree->{$key} )){

      if( $ref eq 'HASH' ){

        # hash references are scanned via recursion
        my %new_value_of = scan_hash( $hash_tree->{$key}, @keys );

        # stored using slices: http://perldoc.perl.org/perldata.html#Slices
        @value_of{ keys %new_value_of } = values %new_value_of;

      }else{
        die "cannot handle a $ref reference\n";
      }

    } # end if

  } # end for

  return %value_of;
}
person shawnhcorey    schedule 16.07.2013