1

私は完全に問題に固執しています:

いくつかの巨大なマルチレベル hash_tables を持ついくつかの巨大な perl スクリプトがあります。すべて正常に動作しますが、コードと読みやすさを減らすために、最後のハッシュ参照をサブ関数に渡したいと思います。

前述のように、%hash_table1 と %hash_table2 など、いくつかの異なるハッシュ テーブルがあり、どちらも同じ値ですが、キーのレベルが異なります。

3 レベルのキーを持つ hash_table1:

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

他の hash_table にも同じ「値」がありますが、マルチレベルが異なります: 2 レベルのキーを持つ hash_table2:

$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}});
      }
   }
}

2 レベルの hash_table にアクセスするコードを別の場所で終了します。

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}});
   }
}

前述のように、基本的にすべての保存された値に一度にアクセスするために、最後のハッシュ参照をサブ関数に渡す実用的なソリューションがあればいいのにと思います。

有益なコメントをお寄せいただきありがとうございます。

ではごきげんよう、

オールドマクファンジー

4

4 に答える 4

1

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";
}
于 2013-07-16T17:16:58.833 に答える
0
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} }
         }
      );
   }
}

申し訳ありませんが、説明の時間はありません。

于 2013-07-16T17:20:34.563 に答える
0
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}と、おそらく問題が解決します。また、常にstrictとwarningを使用してください。

于 2013-07-16T17:58:09.177 に答える
0

これは機能するはずですが、テストするための複雑なハッシュはありません。:)

# --------------------------------------
#       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;
}
于 2013-07-16T17:59:38.683 に答える