Slicing a nested hash in Perl

2019-05-01 06:17发布

问题:

Say I have a hash that I can index as:

$hash{$document}{$word}

From what I read online (although I could not find this on perlreftut, perldsc or perllol), I can slice a hash using a list if I use the @ prefix on my hash to indicate that I want the hash to return a list. However, if I try to slice my hash using a list @list:

@%hash{$document}{@list}

I get several "Scalar values ... better written" errors.

How can I slash a nested hash in Perl?

回答1:

The sigill for your hash must be @, like so:

@{$hash{$document}}{@list}

Assuming @list contains valid keys for %hash it will return the corresponding values, or undef if the key does not exist.

This is based on the general rule of a hash slice:

%foo = ( a => 1, b => 2, c => 3 );
print @foo{'a','b'};               # prints 12
%bar = ( foo => \%foo );           # foo is now a reference in %bar
print @{ $bar{foo} }{'a','b'};     # prints 12, same data as before


回答2:

First, when you expect to get a list from a hash slice, use @ sigil first. % is pointless here.

Second, you should understand that $hash{$document} value is not a hash or array. It's a reference - to a hash OR to an array.

With all this said, you might use something like this:

@{ $hash{$document} }{ @list };

... so you dereference value of $hash{$document}, then use a hash slice over it. For example:

my %hash = (
    'one' => {
        'first'  => 1,
        'second' => 2,
     },
     'two' => {
        'third'  => 3,
        'fourth' => 4,
     } 
);

my $key  = 'one';
my @list = ('first', 'second');

print $_, "\n" for @{ $hash{$key} }{@list};
# ...gives 1\n2\n


标签: perl hash slice