0

Given a hash, and a list of keys how do I get access to the value specified by the keys?

In other words given:

my $h = {};

my @key = qw(hello to everyone);

how do I get to

$h->{hello}->{to}->{everyone}

in one go?

simone
  • 4,667
  • 4
  • 25
  • 47
  • 1
    Does this answer your question? [Referring to a chain of hash keys in a Perl hash of hashes](https://stackoverflow.com/questions/22774118/referring-to-a-chain-of-hash-keys-in-a-perl-hash-of-hashes) – pii_ke Apr 04 '21 at 11:07
  • See also [How to access a hash value by index stored in variable](https://stackoverflow.com/q/58674386/2173773) and [Perl How to build a Dynamic multi level hash lookup](https://stackoverflow.com/q/41029468/2173773) – Håkon Hægland Apr 04 '21 at 11:10
  • 1
    @HåkonHægland - yes, similar questions. My primary purpose here is to share broadly this elegant solution. The secondary one is to be able to find it easily (not having to dig through years of bookmarks). – simone Apr 04 '21 at 11:36
  • @pii_ke - yes, very similar, somewhat more concise solution. See also the previous commenr. I'm ok with suggestions on how to handle in an alternative way – simone Apr 04 '21 at 11:37
  • Also, [How to create recursive hash of hash ? (With unlimited deep)](https://stackoverflow.com/q/37408725/589924) which has the proper use of Data::Diver and a short no-module solution. – ikegami Apr 04 '21 at 18:07

1 Answers1

2

Not my answer - credit goes to Merlyn on PerlMonks via Polettix.

use List::Util;

sub pointer_to_element {
    return reduce(sub { \($$a->{$b}) }, \shift, @_);
}

my $h = { hello => {to => 'everyone'} };

my @key = qw/hello to/;

# get the element
my $scalar_ref = pointer_to_element($h, @key);
print $$scalar_ref, "\n";    # prints "everyone"

# set the element
$$scalar_ref = 'everybody';

# and check it
print "$hash{hello}{to}\n";  # prints "everybody"

Putting it here because it's a gem and for ease of Googling for everyone.

I hope it's ok with the original authors (and if not I'll delete this).

simone
  • 4,667
  • 4
  • 25
  • 47