Here's your structure:
{
Fred => {
"Street Name" => ["First Avenue"],
"animal" => ["lion", "snake", "spider", "monkey"],
},
Dave => {
"Street Name" => ["Church Street"],
"animal" => ["dog", "cat", "pig", "elephant"],
},
}
Let's take this apart one level at a time. There's three levels here:
The outer level represents a hash I'll call %person_hash
. Your hash has two keys in it: Fred
and Dave
. Each of the values of the these two hashes point (reference) other hashes. That is $person_hash{Dave}
is a hash reference and $person_hash{Fred}
is a hash reference.
To turn those two hash references into hashes, I use the dereferencing syntax:
%attribute_hash = %{ $person_hash{Dave} };
Now, we have a hash called %attribute_hash
. This %attribute_hash
contains attributes for Fred and Dave. In your example, there are two elements in each of these %attribute_hash
hashes (Remember: There's one for Dave and one for Fred). The two keyed elements in these %attribute_hash
hashes contain "Street Address" and "animal".
To access the lists, I can use the dereferencing syntax: @values = @{ $attribute_hash{$attribute} }
.
So, let's look at how we can print all of this out:
use strict;
use warnings;
use feature qw(say);
my %person_hash = (
Fred => {
"Street Name" => [ "First Avenue" ],
animal => [ "lion", "snake", "spider", "monkey" ],
},
Dave => {
"Street name" => [ "Church Street" ],
animal => [ "dog", "cat", "pig", "elephant" ],
},
);
# The first level contains the keys `Dave` and `Fred`
for my $person ( keys %person_hash ) {
say "The person is $person";
# The keys will be for "Dave" and "Fred", and will be the value
# of $person. This is a hash reference, so let's dereference it.
my %attribute_hash = %{ $person_hash{$person} };
# We have a hash of attributes beloning to that person. The
# attributes will be "Street Name" and "animal"
for my $attribute ( keys %attribute_hash ) {
say " ${person}'s attribute is '$attribute'";
# Each "attribute" points to a list. Let's get the list
my @value_list = @{ $attribute_hash{$attribute} };
# Now we can go through that list:
for my $value ( @value_list ) {
say " ${person}'s attribute '$attribute' has a value of $value";
}
}
}
This prints out:
The person is Dave
Dave's attribute is 'Street name'
Dave's attribute 'Street name' has a value of Church Street
Dave's attribute is 'animal'
Dave's attribute 'animal' has a value of dog
Dave's attribute 'animal' has a value of cat
Dave's attribute 'animal' has a value of pig
Dave's attribute 'animal' has a value of elephant
The person is Fred
Fred's attribute is 'Street Name'
Fred's attribute 'Street Name' has a value of First Avenue
Fred's attribute is 'animal'
Fred's attribute 'animal' has a value of lion
Fred's attribute 'animal' has a value of snake
Fred's attribute 'animal' has a value of spider
Fred's attribute 'animal' has a value of monkey
You should also know that I can access the values directly inside these by using the ->
syntax:
say "Fred's first animal in his list is " . $person_hash{Fred}->{animal}->[0];
I can also use that syntax when I dereference:
say "Fred's animals are " . join ", ", @{ $person_hash->{Fred}->{animal} };
Note that $person_hash->{Fred}->{animal}
is a reference to the array that contains the animals.