Perl | Multidimensional Hashes

    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.

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    # !/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);

    chevron_right

    
    

    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:

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    for $key (keys %hash
    {
        print "$key: \n";
        for $ele (keys %{$hash{$key}})
        {
            print "  $ele: " . $hash{$key}->{$ele} . "\n";
        }
    }

    chevron_right

    
    

    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:

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    while (($key, $ele) = each %hash
    {
        print "$key: \n";
        while (($ele, $sub_ele) = each %$ele
        {
            print " $ele = $sub_ele ";
        }
        print "\n";
    }

    chevron_right

    
    

    Following example illustrates the traversing through a multidimensional hash using For and while loops:
    Example:

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    # !/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";
    }

    chevron_right

    
    

    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.

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    # !/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";
    }

    chevron_right

    
    

    Output:

    Sales department exists.
    Albert is Salesman of Sales department.
    


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.