How to dereference a reference to a hash or to an array in Perl
Given a reference to hash or a reference to an array in Perl, how can we get back the original hash or array?
What if we have a reference to a reference to a hash and we would like to get back the reference to the hash.
Dereference a HASH
In the first example we crate a reference to a hash (we call it $hr). First we print it out directly so you can see it is really a reference to a HASH. Then we print out the content using the standard Data::Dumper module.
Then we de-reference it by putting a % sign in-front of it %$hr and copy the content to another variable called %h.
Then we can see how to access the element of this new hash and how to access the same elements using the hash-reference we already had earlier. For this first we use the "arrow notation" and then the "stacking sigils notation". I always prefer the "arrow notation".
/examples/hash_deref.pl
use 5.010; use strict; use warnings; use Data::Dumper qw(Dumper); my $hr = { name => 'Foo', email => 'foo@corp.com', }; say $hr; say Dumper $hr; my %h = %$hr; say $h{name}; say $hr->{name}; # arrow notation - this is the preferred one! say $$hr{name}; # stacked sigils - not recommended
The output will look like this:
HASH(0x7ff9c7004680) $VAR1 = { 'email' => 'foo@corp.com', 'name' => 'Foo' }; Foo Foo Foo
Dereference an ARRAY
In the second example we create a reference to and ARRAY and assign it to $ar. We go through the same steps except that here we prefix the reference using @ to de-reference it gaining the @$ar expression.
Here too we have both the "arrow notation" and the "stacked sigils notation" and here to I'd recommend the former.
/examples/array_deref.pl
use 5.010; use strict; use warnings; use Data::Dumper qw(Dumper); my $ar = ['apple', 'banana', 'peach']; say $ar; say Dumper $ar; my @a = @$ar; say $a[0]; say $ar->[0]; # "arrow notation" recommended say $$ar[0];
ARRAY(0x7f8954803c80) $VAR1 = [ 'apple', 'banana', 'peach' ]; apple apple apple
Getting the reference from a reference to a reference to a hash
Sounds complex, but the code is quite simple.
We have a reference to a hash of hashes in the $hr. The data structure in our example is actually built of three hashes. The main hash has two keys "player_a" and "player_b". The value of each key is a reference to hash by itself.
If we access the value of one of the keys of the main hash: $hr->{player_a} we get to the reference of one of the internal hashes.
Hence in the output we see 3 HASH references as the first 3 lines of output.
Then using Data::Dumper we can see that at least the one provides access to one of the internal hashes.
Finally we can see how to access an element inside on of internal hashes.
/examples/hash_of_hash_deref.pl
use 5.010; use strict; use warnings; use Data::Dumper qw(Dumper); my $hr = { player_a => { name => 'Foo', email => 'foo@corp.com', }, player_b => { name => 'Bar', email => 'bar@corp.com', }, }; say $hr; say $hr->{player_a}; say $hr->{player_b}; say Dumper $hr->{player_a}; say $hr->{player_b}{name};
HASH(0x7fff3d828db0) HASH(0x7fff3d804680) HASH(0x7fff3d828c78) $VAR1 = { 'name' => 'Foo', 'email' => 'foo@corp.com' }; Bar
Comments
The core of every program. Thanks for sharing.
Hi Gabor. Thanks for your article. I can't see where you said WHY you prefer arrow notation over stacked sigils. Why do you prefer it? Cosmetics? Risk? --- It looks much more readable to me, less confusing, and indeed less error-prone.
Thanks much. Does line 15 in /examples/hash_deref.pl:
my %h = %$hr;
triggers deep copy of the hash?
--- no
Would love to see an explanation of how to reference a hash element contained within an array of hashes. Trying to figure that out now. I know the hash I want is the first in the array, but having trouble determining how to access it, in print for example; $arrayOfHashes->[0] has the hash I want, and the hash itself in that element has a value stored in hash key 'ID'. Tried things like %{@arrayOfHashes->[0]}->{ID} etc. but haven't found the magical combo.
--- $arrayOfHashes->[0]->{ID} or in shorter: $arrayOfHashes->[0]{ID}
--- Thanks!
---
use Data::Dumper to print out what is in %hash and what is in $ref. That will help you.
Published on 2017-12-17