Skip to content

Perl Hashes

A hash in Perl is an unordered collection of key-value pairs. Hashes are also known as associative arrays or dictionaries in other languages. Hash variable names are prefixed with a percent sign (%), e.g., %my_hash. To access a single element (a value) from a hash, you use a dollar sign ($) before the hash name, followed by the key in curly braces, e.g., $my_hash{'some_key'} or $my_hash{some_key} if the key is a simple bareword.

Keys in a Perl hash are always strings. If you use a number as a key, Perl will convert it to its string representation. Values can be any scalar (number, string, or reference).

Here is a simple example:

#!/usr/bin/perl
use strict;
use warnings;
my %student_ages = (
'Alice' => 22,
'Bob' => 24,
'Charlie' => 21,
);
print "Alice's age: $student_ages{'Alice'}\n";
print "Bob's age: $student_ages{'Bob'}\n";
# Using bareword for key (if simple enough, quotes are optional with =>)
my %capitals = (
USA => "Washington D.C.",
UK => "London",
Japan => "Tokyo",
);
print "Capital of UK: $capitals{UK}\n";

This will produce:

Alice's age: 22
Bob's age: 24
Capital of UK: London

Hashes can be created in several ways:

  1. Assigning key-value pairs one by one:
my %user_data;
$user_data{'name'} = "David";
$user_data{'id'} = 101;
$user_data{'email'} = 'david@example.com';
  1. Using a list of key-value pairs: The list is interpreted as alternating keys and values.
my %contact_info = ('name', 'Eve', 'phone', '555-1234', 'city', 'New City');
  1. Using the => (fat comma) operator: This is an alias for the comma but improves readability by visually pairing keys and values. It also auto-quotes its left-hand operand if it’s a bareword (a simple string that looks like an identifier). This is the most common and recommended way.
my %book_details = (
title => "The Modern Perl Handbook",
author => "Perl Hacker",
year => 2023,
ISBN => "978-0123456789", # Keys are strings
);

To retrieve a value, use the $ sigil with the hash name and the key in curly braces. If a key does not exist, accessing it returns undef.

#!/usr/bin/perl
use strict;
use warnings;
my %config = (
host => "localhost",
port => 8080,
timeout => 30,
);
print "Host: $config{'host'}\n";
print "Port: $config{port}\n"; # Bareword key in access
my $non_existent_value = $config{'user'}; # Key 'user' doesn't exist
if (defined $non_existent_value) {
print "User: $non_existent_value\n";
} else {
print "User key is not defined.\n";
}

Output:

Host: localhost
Port: 8080
User key is not defined.

A hash slice allows you to retrieve multiple values from a hash at once by providing a list of keys. Use the @ sigil (as you are getting a list of values).

#!/usr/bin/perl
use strict;
use warnings;
my %fruit_colors = (
apple => "red",
banana => "yellow",
grape => "purple",
orange => "orange",
);
my @selected_keys = ('apple', 'grape', 'kiwi'); # 'kiwi' doesn't exist
my @colors = @fruit_colors{@selected_keys};
# or directly: my @colors = @fruit_colors{'apple', 'grape', 'kiwi'};
print "Colors found: " . join(", ", grep { defined } @colors) . "\n";
# grep filters out undef for non-existent keys
# For 'kiwi', its corresponding value in @colors will be undef.

Output:

Colors found: red, purple

The keys %HASH function returns a list of all keys in the hash (in an apparently random order). The values %HASH function returns a list of all values (in the same order as their corresponding keys from keys %HASH if called on the same unmodified hash).

#!/usr/bin/perl
use strict;
use warnings;
my %days_in_month = (
January => 31,
February => 28, # Ignoring leap years for simplicity
March => 31,
);
my @months = keys %days_in_month;
print "Months: " . join(", ", sort @months) . "\n";
my @num_days = values %days_in_month;
print "Number of days (in some order): " . join(", ", @num_days) . "\n";
# Iterating over key-value pairs
while (my ($month, $days) = each %days_in_month) {
print "$month has $days days.\n";
}
# Note: `each` iterates in an apparently random order. Modifying the hash while iterating with `each` can lead to issues.

Output (order of months/days might vary for unsorted keys/values and each):

Months: February, January, March
Number of days (in some order): 28, 31, 31
January has 31 days.
March has 31 days.
February has 28 days.

The exists $HASH{key} function returns true if the specified key exists in the hash, even if its value is undef. This is different from checking defined $HASH{key}, which checks if the value associated with the key is defined.

#!/usr/bin/perl
use strict;
use warnings;
my %settings = (
user => "admin",
level => 5,
theme => undef, # Key exists, but value is undef
);
if (exists $settings{'theme'}) {
print "'theme' key exists.\n";
} else {
print "'theme' key does not exist.\n";
}
if (defined $settings{'theme'}) {
print "Value for 'theme' is defined: $settings{'theme'}\n";
} else {
print "Value for 'theme' is not defined (it's undef).\n";
}
if (exists $settings{'password'}) {
print "'password' key exists.\n";
} else {
print "'password' key does not exist.\n";
}

Output:

'theme' key exists.
Value for 'theme' is not defined (it's undef).
'password' key does not exist.

To find the number of key-value pairs in a hash, evaluate the hash in scalar context, or evaluate keys %HASH or values %HASH in scalar context. The most direct way is often scalar %HASH when the hash is guaranteed to have pairs, but scalar keys %HASH is very common and explicit.

#!/usr/bin/perl
use strict;
use warnings;
my %inventory = (
apples => 100,
bananas => 150,
oranges => 75,
);
my $num_items_method1 = scalar(keys %inventory);
print "Number of item types (method 1): $num_items_method1\n";
# In scalar context, a hash used in a numeric context returns true if it has elements, false otherwise.
# To get the count of pairs, you usually use keys or values in scalar context.
# A more idiomatic way to get the count of keys:
my $key_count = keys %inventory; # In scalar context, keys returns number of keys
print "Number of item types (method 2): $key_count\n";
# If a hash is empty, scalar context returns false (empty string or 0 depending on use)
my %empty_hash;
if (%empty_hash) {
print "Empty hash is true in boolean context (this won't print for truly empty hash after Perl 5.22)\n";
} else {
print "Empty hash is false in boolean context.\n";
}
# Prior to Perl 5.22, an empty hash in boolean scalar context was true.
# From 5.22 onwards, it's false. This behavior was somewhat problematic.
# The reliable way to check for emptiness is `if (keys %empty_hash)`.

Output:

Number of item types (method 1): 3
Number of item types (method 2): 3
Empty hash is false in boolean context.

Add or update a key-value pair using simple assignment: $HASH{new_key} = $value;. To remove a key-value pair, use the delete $HASH{key} function. delete returns the value associated with the deleted key (or undef if the key didn’t exist).

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper; # For pretty-printing the hash
my %employee_data = (
101 => "Alice",
102 => "Bob",
);
print "Initial: " . Dumper(\%employee_data);
# Add a new employee
$employee_data{103} = "Charlie";
print "After add: " . Dumper(\%employee_data);
# Update an existing employee's name
$employee_data{101} = "Alicia";
print "After update: " . Dumper(\%employee_data);
# Remove an employee
my $deleted_value = delete $employee_data{102};
print "Deleted Bob. Value was: $deleted_value\n";
print "After delete: " . Dumper(\%employee_data);

Output (exact Dumper format might vary slightly):

Initial: $VAR1 = {
'101' => 'Alice',
'102' => 'Bob'
};
After add: $VAR1 = {
'101' => 'Alice',
'102' => 'Bob',
'103' => 'Charlie'
};
After update: $VAR1 = {
'101' => 'Alicia',
'102' => 'Bob',
'103' => 'Charlie'
};
Deleted Bob. Value was: Bob
After delete: $VAR1 = {
'101' => 'Alicia',
'103' => 'Charlie'
};