Hashes can be understood as lookup-tables. You can access its contents by specifiying a key for each of them. Keys must be strings. If they're not, they will be converted to strings.
If you give the hash simply a known key, it will serve you its value.
# Elements are in (key, value, key, value) sequence
my %inhabitants_of = ("London", 8674000, "Paris", 2244000);
# You can save some typing and gain in clarity by using the "fat comma"
# syntactical sugar. It behaves like a comma and quotes what's on the left.
my %translations_of_hello = (spanish => 'Hola', german => 'Hallo', swedish => 'Hej');
In the following example, note the brackets and sigil: you access an element of %hash
using $hash{key}
because the value you want is a scalar. Some consider it good practice to quote the key while others find this style visually noisy. Quoting is only required for keys that could be mistaken for expressions like $hash{'some-key'}
my $greeting = $translations_of_hello{'spanish'};
While Perl by default will try to use barewords as strings, +
modifier can also be used to indicate to Perl that key should not be interpolated but executed with result of execution being used as a key:
my %employee = ( name => 'John Doe', shift => 'night' );
# this example will print 'night'
print $employee{shift};
# but this one will execute [shift][1], extracting first element from @_,
# and use result as a key
print $employee{+shift};
Like with arrays, you can access multiple hash elements at the same time. This is called a hash slice. The resulting value is a list, so use the @
sigil:
my @words = @translations_of_hello{'spanish', 'german'}; # ('Hola', 'Hallo')
Iterate over the keys of an hash with keys
keys
will return items in a random order. Combine with sort
if you wish.
for my $lang (sort keys %translations_of_hello) {
say $translations_of_hello{$lang};
}
If you do not actually need the keys like in the previous example, values
returns the hash's values directly:
for my $translation (values %translations_of_hello) {
say $translation;
}
You can also use a while loop with each
to iterate over the hash. This way, you will get both the key and the value at the same time, without a separate value lookup. Its use is however discouraged, as each
can break in mistifying ways.
# DISCOURAGED
while (my ($lang, $translation) = each %translations_of_hello) {
say $translation;
}
Access to unset elements returns undef, not an error:
my $italian = $translations_of_hello{'italian'}; # undef
map
and list flattening can be used to create hashes out of arrays. This is a popular way to create a 'set' of values, e.g. to quickly check whether a value is in @elems
. This operation usually takes O(n) time (i.e. proportional to the number of elements) but can be done in constant time (O(1)) by turning the list into a hash:
@elems = qw(x y x z t);
my %set = map { $_ => 1 } @elems; # (x, 1, y, 1, t, 1)
my $y_membership = $set{'y'}; # 1
my $w_membership = $set{'w'}; # undef
This requires some explanation. The contents of @elems
get read into a list, which is processed by map
. map
accepts a code block that gets called for each value of its input list; the value of the element is available for use in $_
. Our code block returns two list elements for each input element: $_
, the input element, and 1
, just some value. Once you account for list flattening, the outcome is that map { $_ => 1 } @elems
turns qw(x y x z t)
into (x => 1, y => 1, x => 1, z => 1, t => 1)
.
As those elements get assigned into the hash, odd elements become hash keys and even elements become hash values. When a key is specified multiple times in a list to be assigned to a hash, the last value wins. This effectively discards duplicates.
A faster way to turn a list into a hash uses assignment to a hash slice. It uses the x
operator to multiply the single-element list (1)
by the size of @elems
, so there is a 1
value for each of the keys in the slice on the left hand side:
@elems = qw(x y x z t);
my %set;
@set{@elems} = (1) x @elems;
The following application of hashes also exploits the fact that hashes and lists can often be used interchangeably to implement named function args:
sub hash_args {
my %args = @_;
my %defaults = (foo => 1, bar => 0);
my %overrides = (__unsafe => 0);
my %settings = (%defaults, %args, %overrides);
}
# This function can then be called like this:
hash_args(foo => 5, bar => 3); # (foo => 5, bar => 3, __unsafe ==> 0)
hash_args(); # (foo => 1, bar => 0, __unsafe ==> 0)
hash_args(__unsafe => 1) # (foo => 1, bar => 0, __unsafe ==> 0)
When used as booleans, hashes are true if they are not empty.