| |
Perl Hashes
NEW!!!
Check my new resource: Perl How To Tutorial eBooks
Perl Hashes Menu:
Defining hashes One-dimensional hashes Copy a hash Create or initialize a hash Empty or clear a hash Extract slices from a hash Find out if a hash variable contains references Get the size of a hash Insert or add new items into a hash Loop or iterate through a hash Print a hash Remove a key from a hash Sort or order a hash Reverse a hash
After scalars and arrays, Perl hashes (or Perl associative arrays) represent the third native built-in data type of Perl language. By scalar we mean the simplest Perl data type which was designed to hold only one thing like a number, a string or a reference. The array is a more complex data type which is meant to hold collections of scalars. For each of these built-in data type variables, Perl language has a special symbol which precedes the variable name: $ for scalar, @ for array and % for hash.Perl Hashes (associative arrays) are most like arrays but there are some significant differences, too. An array has a number of elements (scalars) and to access one particular element we use the index (or subscript) of that element, where the first element has the index 0, the next one 1, and so on. A hash contains a number of scalars, too. But in this case an element of the structure represents a pair of two parts – a key and a value. Whenever we refer to an element of a Perl hash structure, we mean a pair which links a value to a key. We have access at the elements of a hash variable by a scalar key and not by an index (like in arrays). In Perl language, the hash structure is based upon a Perl hash table that associates keys with values. In order o retrieve an element of a hash variable, we must supply a key and find the corresponding value. The keys are unique but for different keys we can have identical values. Note: I tested all the examples below on a Windows machine, Perl v5.8.8. If you want to run them on Linux, don’t forget to insert at the beginning of the script the following line: back to top
By one-dimensional Perl hash or simple hash we generally mean a hash whose elements are not references to other Perl structures (arrays or hashes). See %ages and %members hashes shown below for an example:%ages = ("John", 43, "Paul", 25, "Marie", 22);
%members = (John => "father", Paul => "son",
Marie => "daughter");
back to top
%destHash = %sourceHash; # copy a hash
$destHasRef = $sourceHashRef; # copy a hash ref
This is a shallow method to copy Perl hashes, and works well when we speak about one–dimensional hashes, with no references to other structures.
back to top
Perl hashes are structures and you do not need to allocate structures or other variables in Perl. The first time you use a hash type variable in your code, that variable will be automatically created. Please look at the following code:%ages = ("John", 43, "Paul", 25, "Marie", 22);
%members = (John => "father", Paul => "son",
Marie => "daughter");
$agesRef = \%ages;
print $$agesRef{Marie}; #prints 22
In the above example, we used two ways to create/initialize a hash variable. In the first line we initialized the %ages hash variable with a list composed by pairing of keys and values, separated by commas. But Perl has a special "comma-arrow" (=>) operator that we used to initialize the %members hash variable in the second line of code. The left side of the comma-arrow operator is expected to be a simple string and therefore it is not necessary to be quoted. The third line shows you how to define a hash reference in Perl. You can dereference Perl hashes using the notation %$hashRef. If you want to get a certain hash value, you can dereference it by using the notation $$hashRef{key} – the fourth line of the above snippet code shows you how to do that. I’ll show you below the Perl hash table for both the %ages and %members hash variables. %ages | key | value | | John | 43 | | Paul | 25 | | Marie | 22 | %members | key | value | | John | father | | Paul | son | | Marie | aughter | back to top
In order to initialize Perl hashes to an empty list, you can use the code line: After the initialization, all the elements of the hash will be deleted.back to top
Perl lets you extract slices from Perl hashes. Please look at the following code:# define a hash
%cds = ("Dr. Hook" => "Sylvias Mother",
"Rod Stewart" => "Maggie May",
"Andrea Bocelli" => "Romanza",
"Kenny Rogers" => "For the good times",
"Bee Gees" => "One night only",
"Bonnie Tyler" => "Hide your heart");
# we used the @ prefix because the return value
# represents a list
# we need to supply the keys for which we wanted
# to extract the values
@slice = @cds{"Dr. Hook","Kenny Rogers","Bee Gees"};
# we used the join function to print each string
# on a new line
print join("\n", @slice);
Running the code it will produce the output: Sylvias Mother
For the good times
One night only
back to top
An easy way to find out if a variable is a simple string or number, or a reference to an array or a hash or something else, is to use the ref function. The ref function has the syntax form:If EXPR is not specified, $_ will be used. This function returns an empty string if the EXPR/$_ is not a reference, and a string (the type of reference) otherwise. Look at the code below to see how it works: # define some simple variables
# we can use the same name – colors for different things
$colors = "darkblue";
@colors = qw(blue, red, yellow, brown);
%colors = (c1 => "blue", c2 => "green", c3 => "yellow");
# define a hash with references
%moreColors = (1 => "white", 2 => \$colors,
3 => \@colors, 4 => \%colors);
# loop through %moreColors hash to find out the references
foreach $key (keys %moreColors)
{
if (ref $moreColors{$key} eq "SCALAR") {
print "$key: SCALAR\n";
} elsif (ref $moreColors{$key} eq "ARRAY") {
print "$key: ARRAY\n";
} elsif (ref $moreColors{$key} eq "HASH") {
print "$key: HASH\n";
} elsif (ref $moreColors{$key} eq "") {
print "$key: NO REFERENCE\n";
}
}
And here is what you get as output if you run the code: 4: HASH
1: NO REFERENCE
3: ARRAY
2: SCALAR
Do you see the order (4 1 3 2) in which the keys were printed? Perl doesn’t care about the sequential order (1 2 3 4) in which I initialized %moreColors hash! Remember, if you want to print Perl hashes in some order, you must sort the hashes yourself. (see "Sort or order a hash").
back to top
If you want to find out the number of elements of Perl hashes - or the Perl hash size, you can use the scalar context of its keys, like in the following example:%time = (hour => 12, min =>25, sec => 32, msec =>75);
$size = scalar keys %time; # explicit scalar context - or
$size = keys %time; # implicit scalar context - or
$timeRef = \%time; # using a reference
$size = keys %$timeRef;
print "Hash size: $size\n"; # prints Hash size: 4
back to top
To insert a new (key, value) pair in a hash structure, you can use the syntax form:If hash doesn’t exist, it will be created automatically by Perl. Please have a look at the following code to see some examples: %ages = ("John", 43, "Paul", 25, "Marie", 22);
$ages{"Anne"} = 22;
$ages{"Paul"} = 24;
$ages{"Marie"} = 24 unless exists $ages{"Marie"} ;
$ages{"George"} = 51 unless exists $ages{"George"} ;
print %ages, "\n";
In the first line I initialized the %ages hash. In the second and the third lines I inserted two elements in the hash variable. Please beware that the key "Paul" already exists and its associated value was over-written with the new value (24). The next two lines insert only new items into the %ages hash – I used unless exists to check up if a certain key exists in a hash before adding it. Please note the dollar sign in $ages{"Marie"} and remember that a single element of a hash is a scalar. The output of this code is shown below:Anne22George51John43Paul24Marie22
Please note that the hash is not ordered and you couldn’t expect at any order when you display its elements. Because Perl hashes are not ordered, I preferred to use the insert/add verb instead of append (the end of a hash has not particular meaning).
back to top
To loop or iterate through Perl hashes, you can use "each" function. This function iterates or loops through the (key, value) pairs of a hash, each (key, value) pair being returned as a two-element list. See the example below to find out how it works:%phoneNumbers = ("Anne", "432566", "Paul", "231275", "Marie",
"299302");
while (($key, $value) = each %phoneNumbers)
{
print "$key has the phone number $phoneNumbers{$key}\n";
}
The code shown above will extract the keys and values from the %phoneNumbers hash and it will display as output: Anne has the phone number 432566
Paul has the phone number 231275
Marie has the phone number 299302
(see Print a hash for another way to loop through Perl hashes)
back to top
I’ll show you how to print the keys/values of Perl hashes. I’ll assign some elements to a hash structure (by using the syntax: $hash{$key}=value;), then I’ll iterate through the elements of the hash structure in order to print its keys/values pairs, as you see in the following snippet code:# I’ll create a new hash - %notebookPrices
# by assigning some elements to it:
$notebookPrices{"Toshiba"}=650;
$notebookPrices{"HP"}=550;
$notebookPrices{"Acer"}=750;
# the next loop prints the keys/values of the hash
foreach $key (keys %notebookPrices)
{
print "Key: $key, Value: \$$notebookPrices{$key}\n";
}
After running this code, you’ll get the output: Key: Acer, Value: $750
Key: Toshiba, Value: $650
Key: HP, Value: $550
Note that Perl does not have a default order for the elements of a hash.
back to top
If you want to remove a single hash (key, value) pair from Perl hashes, you can use the delete function, in one of the following syntax forms:delete $hash{$key};
delete $hashRef->{$key}; # if you have a hash reference
delete $$hashRef{$key}; # if you have a hash reference
See the examples below about how to implement it: %phoneNumbers = ("Anne", "408566", "Paul", "233375", "Marie",
"217302");
delete $phoneNumbers {"Paul"};
delete $phoneNumbers {"John"};
$phoneNumbersRef = \%phoneNumbers;
delete $$phoneNumbersRef{"Anne"};
#print the hash (keys, values)
foreach $key (keys % phoneNumbers)
{
print "Key: $key, Value: $phoneNumbers{$key}\n";
}
The second line of this snippet code will have as effect the deletion of the "Paul" key from the %phoneNumbers hash. In the third line of the code we try to delete an inexistent key from the hash, the script will not return any error and the %phoneNumbers hash will remain unchanged. The last line of the above code shows you how to delete a key when you have a hash reference (we used $$hashRef{$key} notation to dereference a certain hash value, but you can use $hashRef->{$key}, too).
back to top
Perl hashes are not ordered and you must not rely on the order in which you added the hash items – Perl uses internally its own way to store the items. You can sort a hash either by keys or values, using the sort function.To sort a hash by key, you can use the following code lines: # define a hash
%time = (hour => 12, min => 25, sec => 32, msec =>75);
# foreach loop
foreach $key (sort keys %time)
{
print "$key: $time{$key}\n";
}
To sort a hash by value, in a descending order, you can use the following code: # define a hash
%v = (v1 => 75, v2 => 251, v3 => 3, v4 => 12);
# sort by value and put the keys in an array
@keys = sort {$v{$b} <=> $v{$a}} keys %v;
# loop through array to print the hash pairs ordered
foreach $key (@keys)
{
print "$key: $v{$key}\n";
}
If you will run the code, it will produce the following output: v1: 251
v3: 75
v2: 12
v4: 3
In the example above, our hash has numerical values so we used the numerical operator "<=>" for the comparisons. If you want to sort the values lexically, you need to use the stringwise operator "cmp" instead of "<=>". back to top
Because a hash represents a list of (key, value) pairs, we can reverse such a list and after that each pair will become (value, key). We'll do this by using the reverse function. However, beware that the hash keys are unique and if the values of the source hash are not unique, some elements will be lost. I want to say that if you reverse again your resulting hash, it’s possible to obtain a shorter hash. Here is an example how you can implement it:# define a hash
%cds = ("Dr. Hook" => "Sylvias Mother",
"Andrea Bocelli" => "Romanza",
"Bonnie Tyler" => "Hide your heart");
%cdsReversed = reverse %cds;
# we’ll use Data::Dumper module to see
# what it is in the hash
use Data::Dumper;
print Dumper(%cdsReversed);
after running this code, we’ll get as output: $VAR1 = 'Sylvias Mother';
$VAR2 = 'Dr. Hook';
$VAR3 = 'Hide your heart';
$VAR4 = 'Bonnie Tyler';
$VAR5 = 'Romanza';
$VAR6 = 'Andrea Bocelli';
back to top
If you want to download the Perl hashes script with all the above examples included, please click here: Script download
NEW!!!
Do you want more information about the basic Perl topics?
Check my new "Perl How To" Tutorial eBooks page where I'll answer the most frequent questions regarding some topics :
Perl How To Tutorial eBooks
Table of Contents:
A Perl Script Install Perl Running Perl Perl Data Types Perl Variables Perl Operators Perl Lists Perl Arrays Array Size Array Length Perl Hashes Perl Statements Perl if Perl unless Perl switch Perl while Perl do-while Perl until Perl do-until Perl for Perl foreach Built-in Perl Functions Functions by Category String Functions Array Functions Functions in alphabetical order chomp chop chr crypt defined grep hex index join lc lcfirst length oct ord pack pop push reverse rindex shift split substr uc undef unshift
return to Perl Basics
Would you like to create your own website like this one? Hit the Alarm Clock!


|