Perl Hashes
Perl - Hashes
Section titled “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/perluse 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: 22Bob's age: 24Capital of UK: LondonCreating Hashes
Section titled “Creating Hashes”Hashes can be created in several ways:
- Assigning key-value pairs one by one:
my %user_data;$user_data{'name'} = "David";$user_data{'id'} = 101;$user_data{'email'} = 'david@example.com';- 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');- 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);Accessing Hash Elements
Section titled “Accessing Hash Elements”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/perluse 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 existif (defined $non_existent_value) { print "User: $non_existent_value\n";} else { print "User key is not defined.\n";}Output:
Host: localhostPort: 8080User key is not defined.Extracting Slices (Multiple Values)
Section titled “Extracting Slices (Multiple Values)”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/perluse strict;use warnings;
my %fruit_colors = ( apple => "red", banana => "yellow", grape => "purple", orange => "orange",);
my @selected_keys = ('apple', 'grape', 'kiwi'); # 'kiwi' doesn't existmy @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, purpleExtracting Keys and Values
Section titled “Extracting Keys and Values”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/perluse 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 pairswhile (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, MarchNumber of days (in some order): 28, 31, 31January has 31 days.March has 31 days.February has 28 days.Checking for Key Existence
Section titled “Checking for Key Existence”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/perluse 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.Getting Hash Size
Section titled “Getting Hash Size”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/perluse 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 keysprint "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): 3Number of item types (method 2): 3Empty hash is false in boolean context.Adding and Removing Elements in Hashes
Section titled “Adding and Removing Elements in Hashes”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/perluse 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 employeemy $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: BobAfter delete: $VAR1 = { '101' => 'Alicia', '103' => 'Charlie' };