home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


11.2. Making Hashes of Arrays

Problem

For each key in a hash, only one scalar value is allowed, but you'd like to use one key to store and retrieve multiple values. That is, you'd like the value to be a list.

Solution

Use references to arrays as the hash values. Use push to append:

push(@{ $hash{"KEYNAME"} }, "new value");

Then, dereference the value as an array reference when printing out the hash:

foreach $string (keys %hash) {
    print "$string: @{$hash{$string}}\n"; 
} 

Discussion

You can only store scalar values in a hash. References, however, are scalars. This solves the problem of storing multiple values for one key by making $hash{$key} a reference to an array containing the values for $key . The normal hash operations (insertion, deletion, iteration, and testing for existence) can now be written in terms of array operations like push , splice , and foreach .

Here's how to give a key many values:

$hash{"a key"} = [ 3, 4, 5 ];       # anonymous array

Once you have a key with many values, here's how to use them:

@values = @{ $hash{"a key"} };

To append a new value to the array of values associated with a particular key, use push :

push @{ $hash{"a key"} }, $value;

The classic application of these data structures is inverting a hash that has many keys with the same associated value. When inverted, you end up with a hash that has many values for the same key. This is addressed in Recipe 5.8 .

Be warned that this:

@residents = @{ $phone2name{$number} };

causes a runtime exception under use strict because you're dereferencing an undefined reference where autovivification won't occur. You must do this instead:

@residents = exists( $phone2name{$number} )
                ? @{ $phone2name{$number} }
                : ();

See Also

The section on "Hashs of Arrays" in Chapter 4 of Programming Perl and in perldsc (1); Recipe 5.8 ; the example "Tie Example: Make a Hash That Always Appends" in Recipe 13.15