Perl Hashes -- A Guide to Associative Arrays in Perl

Hashes (associative arrays) are an extremely useful data structure in the Perl programming language. A hash is a way of associating one set of values ("keys") with another set of values ("values"); forming a set of key-value pairs.

Let's take a simple example. Suppose we want a Perl structure to associate a collection of people's names with their favorite hobbies.

We'll initialize the hash with some values, add another value, delete a value, access a key-value pair and finally print the whole hash.

use strict; 
use warnings; 

sub main
{
    # Declare and initialize a hash.
    # In this example, both the keys
    # and values are strings. But
    # either or both could be numbers.
    my %hobbies = (
        'Roger' => 'hang gliding',
        'Penny' => 'diving',
        'Peter' => 'bus surfing',
        'Richard' => 'collects spores and fungi',
        'Clare' => 'competitive drinking',
        'Lisa' => 'pole vaulting',
    );
    
    # Add another value to the hash.
    $hobbies{'John'} = 'running';
    
    # Delete a key-value pair from the hash.
    delete $hobbies{'Peter'};
    
    # Access a value.
    print "Richard's hobby: ", $hobbies{'Richard'}, "\n";
    
    # Let's print (display) the entire hash, just
    # for fun. Note that we use a backslash  on the 
    # hash's name. This gives us a reference to 
    # the hash, which we pass to Dumper() to
    # format the hash as a string for display.
    use Data::Dumper;
    print Dumper(%hobbies);
}

main();




Richard's hobby: collects spores and fungi
$VAR1 = {
          'Richard' => 'collects spores and fungi',
          'John' => 'running',
          'Lisa' => 'pole vaulting',
          'Clare' => 'competitive drinking',
          'Penny' => 'diving',
          'Roger' => 'hang gliding'
        };




Notice that when we access an individual (scalar) element of a hash, the % (hash) prefix changes to a $ (scalar) prefix.



Iterating Over Hash Elements in Perl



Often we want to iterate through the different elements of a hash. There are two main ways to do this.


  • 1. use while with each

  • 2. use foreach with keys



The first method is generally more efficient, but sometimes the second method leads to clearer code.

It's very important to remember that the order of hash key-value pairs is not guaranteed to remain constant. The key-value pairs could appear in any order at any time and could change between runs of your program.

my %hobbies = (
    'Roger' => 'hang gliding',
    'Penny' => 'diving',
    'Peter' => 'bus surfing',
    'Richard' => 'collects spores and fungi',
    'Clare' => 'competitive drinking',
    'Lisa' => 'pole vaulting',
);

# Iterate over the hash using each.

print "nUsing each: \n";
while( my ($name, $hobby) = each %hobbies ) {
    print "$name: $hobbyn";
}

print "nUsing keys:\n";

foreach my $name(keys %hobbies) {
    my $hobby = $hobbies{$name};
    
    print "$name: $hobby\n";
}





Using each:
Richard: collects spores and fungi
Lisa: pole vaulting
Clare: competitive drinking
Penny: diving
Peter: bus surfing
Roger: hang gliding

Using keys:
Richard: collects spores and fungi
Lisa: pole vaulting
Clare: competitive drinking
Penny: diving
Peter: bus surfing
Roger: hang gliding




Mainaining Order In Perl Hashes



Since hashes do not maintain an internal order for their contents, if we want an ordered hash, we have to do some extra work.

The easiest option is often just to sort the hash's keys before we use them. Here's an example using first a hash with strings for keys, then a hash with numbers for keys.

my %hobbies = (
    'Roger' => 'hang gliding',
    'Penny' => 'diving',
    'Peter' => 'bus surfing',
    'Richard' => 'collects spores and fungi',
    'Clare' => 'competitive drinking',
    'Lisa' => 'pole vaulting',
);

# Iterate over the hash keys. Use keys to get the 
# keys as an array, sort the array,
# then iterate over the array with foreach.


foreach my $name(sort {$a cmp $b} keys %hobbies) {
    my $hobby = $hobbies{$name};
    
    print "$name: $hobby\n";
}

print "n"; # print a blank line.

# If the hash keys are numbers, you need 
# to use <=> and not cmp to sort.

my %numbers = (
    3 => 'three',
    0 => 'zero',
    2 => 'two',
    1 => 'one',
);

foreach my $digit(sort {$a <=> $b} keys %numbers) {
    my $number = $numbers{$digit};
    
    print "$digit: $number\n";
}




Clare: competitive drinking
Lisa: pole vaulting
Penny: diving
Peter: bus surfing
Richard: collects spores and fungi
Roger: hang gliding

0: zero
1: one
2: two
3: three




Find Out How Many Entries Are In a Hash



You can get all the keys in a hash using keys, which returns all hash keys in an array.

If you want to know how many keys a hash has, just use this array as a scalar value (see Perl Array: Size of an Array for more explanation).

The following displays the number of entries in a hash.

my %sky = (
    'blue' => 'sun',
    'grey' => 'rain',
    'black' => 'night',
    'yellow' => 'storm',
);

print "Entries: ", scalar(keys(%sky)), "\n";




Entries: 4