Если вы знаете, какие предметы вам понадобятся и в каком порядке они вам понадобятся
для ключей, то повторный анализ ключа имеет сомнительную ценность. Я предпочитаю хранить
их в уровнях.
$hash{ $h->{name} }{ $h->{date} } = $h;
# ... OR ...
$hash{ $h->{date} }{ $h->{name} } = $h;
foreach my $name ( sort keys %hash ) {
my $name_hash = $hash{$name};
foreach my $date ( keys %$name_hash ) {
print "\$hash{$name}{$date} => " . Dumper( $name_hash->{$date} ) . "\n";
}
}
Для произвольных уровней может потребоваться функция обхода
sub traverse_hash (&@) {
my ( $block, $hash_ref, $path ) = @_;
$path = [] unless $path;
my ( @res, @results );
my $want = wantarray;
my $want_something = defined $want;
foreach my $key ( %$hash_ref ) {
my $l_path = [ @$path, $key ];
my $value = $hash_ref->{$key};
if ( ref( $value ) eq 'HASH' ) {
@res = traverse_hash( $block, $value, $l_path );
push @results, @res if $want_something && @res;
}
elsif ( $want_something ) {
@res = $block->( $l_path, $value );
push @results, @res if @res;
}
else {
$block->( $path, $value );
}
}
return unless $want_something;
return $want ? @results : { @results };
}
Так что это то же самое, что и выше:
traverse_hash {
my ( $key_path, $value ) = @_;
print( '$hash{' . join( '}{', @$key_path ) . '} => ' . ref Dumper( $value ));
();
} \%hash
;