perlperl-hash

Perl Hash References - Is it possible to put reference to nested hash into 1 variable?


I have a partially nested hash like the following:

$href = {one=>1, word_counts=>{"the"=>34, "train"=>4} };

and I would like to get the value of $href->{'word_counts'}{'train'}. Is it possible to put the {'word_counts'}{'train'} into a variable, so I can access it by simply calling $href->$variable?


Solution

  • There are various ways to do this. I don't think you need to involved $href once you have a shortcut to the value that you want.

    You can take a reference to the value, but then you have to dereference it:

    my $value_ref = \ $href->{'word_counts'}{'train'};
    say $$value_ref;
    

    There's an experimental refaliasing feature where both sides are a reference. Now you don't need to dereference:

    use v5.22;
    \ my $value_ref = \ $href->{'word_counts'}{'train'};
    say $value_ref; # 4
    $value_ref = 17;
    say $href->{'word_counts'}{'train'};  # 17
    

    It's not hard to walk the hash yourself. The trick is to get one level of the hash, store it in a variable, then use that variable to get the next level. Keep going until you are where you want to be:

    my $href = {
        one => 1,
        word_counts => {
            "the" => {
                "dog" => 45,
                "cat" => 24,
                },
            "train" => {
                "car" => 7,
                "wreck" => 37,
                }
            }
        };
    
    my @keys = qw( word_counts train car );
    
    my $temp = $href;
    foreach my $key ( @keys ) {
        die "Not a hash ref at <$key>" unless ref $temp eq ref {};
        die "<$key> not in the hash" unless exists $temp->{$key};
        $temp = $temp->{$key};
        }
    
    print "Value is <$temp>";  # 7