Beyond simple key–value storage, Perl hashes can be nested to form complex data structures. A multidimensional hash (hash of hashes) allows related data to be organized in a clear and flexible way.
- A hash of hashes stores another hash as the value of a primary key.
- It is useful for modeling structured data like records, categories, or hierarchies.
- Its structure is similar to an array of arrays, but uses keys instead of indexes.
- Each primary key maps to a sub-hash containing secondary keys and their values.
Prerequisite: Hashes-Basics
Syntax:
my %hash = (primary_key => {secondary_key => {sub_sec_key => {...}}});Example: Following example shows a hash of hashes that describes a company organization. The primary keys are the departments, and the nested keys are the employee names. The values then contain the corresponding employee’s job title.
# !/usr/bin/perl
# Perl program to demonstrate
# Multidimensional hash
use strict;
use warnings;
use Data::Dumper qw(Dumper);
# Creating a 2D hash
my %company = ('Sales' => {
'Brown' => 'Manager',
'Smith' => 'Salesman',
'Albert' => 'Salesman',
},
'Marketing' => {
'Penfold' => 'Designer',
'Evans' => 'Tea-person',
'Jurgens' => 'Manager',
},
'Production' => {
'Cotton' => 'Paste-up',
'Ridgeway' => 'Manager',
'Web' => 'Developer',
},
);
# Print the List
print Dumper(\%company);
Output
$VAR1 = {
'Sales' => {
'Smith' => 'Salesman',
'Brown' => 'Manager',
'Albert' => 'Salesman'
},
...In above example, the input of the Dumper function is a reference to a data structure and thus we put a back-slash (\) in front of %company.
Note: The order of the keys is random as hashes do not keep them in any specific order.
Some other operations
- To add another anonymous member to the existing hash:
Syntax:
$company{'new_key'} = {'sub_key1' => value1,
'sub_key2' => value2,
'sub_key3' => value3
};
- Access particular value:
Syntax:
print $company{"Production"}{"Web"}; # will output "Developer"- Set value of a particular key:
Syntax:
$company{$Production}->{"Web"} = Senior Developer ; # changes Web to Senior DeveloperTraversing Multidimensional Hashes
To traverse through the multidimensional hash or to go through each value in a hash, simply loop through the keys of the outer hash and then loop through the keys of the inner hashes. For N-dimension hash, N nested or embedded loops are required to traverse through the complete hash. Both For and While loops can be used to loop over to the hash.
Syntax:
for $key (keys %hash)
{
print "$key: \n";
for $ele (keys %{$hash{$key}})
{
print " $ele: " . $hash{$key}->;{$ele} . "\n";
}
}
For large-sized multidimensional hashes, it may be slightly faster to retrieve both keys and the values at the same time using each keyword.
Syntax:
while (($key, $ele) = each %hash)
{
print "$key: \n";
while (($ele, $sub_ele) = each %$ele)
{
print " $ele = $sub_ele ";
}
print "\n";
}
Following example illustrates the traversing through a multidimensional hash using For and while loops:
# !/usr/bin/perl
# Perl program to demonstrate
# Traversing of
# Multidimensional hash
use strict;
use warnings;
use Data::Dumper qw(Dumper);
my %company = ('Sales' => {
'Brown' => 'Manager',
'Smith' => 'Salesman',
'Albert' => 'Salesman',
},
'Marketing' => {
'Penfold' => 'Designer',
'Evans' => 'Tea-person',
'Jurgens' => 'Manager',
},
'Production' => {
'Cotton' => 'Paste-up',
'Ridgeway' => 'Manager',
'Web' => 'Developer',
},
);
print "Traversing hash using For loop: "."\n";
print "\n";
# traversing hash using for loop
for my $key (keys %company)
{
print "$key: \n";
for my $ele (keys %{$company{$key}})
{
print " $ele: " . $company{$key}->{$ele} . "\n";
}
}
print "\nTraversing hash using while" .
"loop using each keyword: " . "\n";
print "\n";
# traversing hash using each keyword
# and while loop
while ((my $key, my $ele) = each %company)
{
print "$key: \n";
while ((my $ele, my $sub_ele) = each %$ele)
{
print " $ele = $sub_ele ";
}
print "\n";
}
Output
Traversing hash using For loop: Production: Cotton: Paste-up Web: Developer Ridgeway: Manager Sales: Brown: Manager Albert: Salesman Smith: Salesman Marketing: Penfold: Designer Evans: Te...
Check for key existence in Multidimensional Hashes
Many times when working with a Perl hash, we need to know if a certain key already exists in the hash. Given a hash, one can check the existence of a particular key by using the exists keyword. In a multidimensional hash like %company used in above examples, one has to use the keyword exists up until the depth level of the key being checked for existence, has been reached.
Syntax:
if (exists($hash{key})) {
if (exists($hash{key}{sub_key})) {
....
}
}One should also be careful using the nth-level construct without trying the (n-1)th-level first as that might trigger unwanted autovivification.
Example: Here's a simple example that demonstrates the Perl exists hash function. In this Perl script, we'll first create a simple Perl hash, and then we'll use the exists function to see if the hash key named 'Albert' exists in the hash.
# !/usr/bin/perl
# Perl program to check for
# existence of a key in a
# Multidimensional hash
use strict;
use warnings;
my %company = ('Sales' => {
'Brown' => 'Manager',
'Smith' => 'Salesman',
'Albert' => 'Salesman',
},
'Marketing' => {
'Penfold' => 'Designer',
'Evans' => 'Tea-person',
'Jurgens' => 'Manager',
},
'Production' => {
'Cotton' => 'Paste-up',
'Ridgeway' => 'Manager',
'Web' => 'Developer',
},
);
# Check for key existence
if (exists $company{"Sales"})
{
print "Sales department exists.\n";
if (exists $company{"Sales"}{"Albert"})
{
print "Albert is " . $company{"Sales"}{"Albert"} .
" of Sales department . \n";
}
else
{
print "Albert is not a member of Sales department.\n";
}
}
else
{
print "Sales department do not exists.\n";
}
Output
Sales department exists. Albert is Salesman of Sales department .