3

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?

jzjzjzjz
  • 43
  • 3

3 Answers3

6

No, but you can use Data::Diver to get a value given a list of keys:

my @keys = ('word_counts', 'train');
my $value = Data::Diver::Dive($href, \(@keys));
ysth
  • 88,068
  • 5
  • 112
  • 203
3

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
brian d foy
  • 121,466
  • 31
  • 192
  • 551
1

In addition to the more general, excellent answers from ysth and brian d foy, consider also a very simple (perhaps too simple) solution:

my @keys = qw( word_counts train);
print $href->{ $keys[0] }{ $keys[1] }; # 4

Note that this solution is repetitive, not elegant (the order of keys is hardcoded), and does not try to walk the hash. But depending on the context and the specific task of the OP, this may be all that is needed.

Timur Shtatland
  • 7,599
  • 2
  • 20
  • 30