Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slicing a nested hash in Perl

Tags:

slice

hash

perl

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?

like image 984
Amelio Vazquez-Reina Avatar asked Sep 17 '12 17:09

Amelio Vazquez-Reina


2 Answers

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
like image 75
TLP Avatar answered Sep 22 '22 01:09

TLP


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
like image 31
raina77ow Avatar answered Sep 20 '22 01:09

raina77ow