Open In App

Perl | Multidimensional Hashes

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report
    Prerequisite: Hashes-Basics

    Introduction

    Beyond the normal constraints of the hashes, we can also create complex structures made up of combinations of two. These are nested or complex structures and they can be used to model complex data in an easy-to-use
    format.

    Among all of the Perl’s nested structures, a Multidimensional hash or Hash of Hashes is the most flexible. It’s like building up a record that itself contains a group of other records.

    The format for creating a hash of hashes is similar to that for array of arrays. Simply, instead of assigning the values to the primary keys in a normal hash, assign a whole hash containing secondary keys and their respective values to the primary keys of the outer hash.

    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 = {
              'Marketing' => {
                               'Evans' => 'Tea-person',
                               'Jurgens' => 'Manager',
                               'Penfold' => 'Designer'
                             },
              'Sales' => {
                           'Smith' => 'Salesman',
                           'Albert' => 'Salesman',
                           'Brown' => 'Manager'
                         },
              'Production' => {
                                'Ridgeway' => 'Manager',
                                'Web' => 'Developer',
                                'Cotton' => 'Paste-up'
                              }
            };
    

    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 Developer

    Traversing 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:
    Example:




    # !/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 by For loop.
    
    Marketing: 
     Evans: Tea-person
     Jurgens: Manager
     Penfold: Designer
    Sales: 
     Brown: Manager
     Albert: Salesman
     Smith: Salesman
    Production: 
     Cotton: Paste-up
     Web: Developer
     Ridgeway: Manager
    
    Traversing hash using while loop with each keyword.
    
    Marketing: 
     Evans=Tea-person  Jurgens=Manager  Penfold=Designer 
    Sales: 
     Brown=Manager  Albert=Salesman  Smith=Salesman 
    Production: 
     Cotton=Paste-up  Web=Developer  Ridgeway=Manager 
    
    

    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.
    


Last Updated : 27 Jun, 2019
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads