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
| Defining hashes |
After scalars and arrays, Perl hashes (or Perl associative arrays) is 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 the Perl language, the hash structure is based upon a Perlhash table that associates keys with values. In order to retrieve an element of a hash variable, you must supply a key and find the corresponding value. The keys are unique but for different keys you can have identical values.
| One-dimensional hashes |
By one-dimensional Perl hashes or simple hashes we generally mean hashes 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"); | Copy a hash |
%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
| Create or initialize a hash |
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 candereference 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 | daughter |
back to top
| Empty or clear a hash |
In order to initialize Perl hashes to an empty list, you can use the code line:
%hash = ();
After the initialization, all the elements of the hash will be deleted.
| Extract slices from a hash |
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
| Find out if a hash variable contains references |
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:
ref EXPR
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
| Get the size of a hash |
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
| Insert or add new items into a hash |
To insert a new (key, value) pair in a hash structure, you can use the syntax form:
$hash{"key"} = "value"; 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";
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
| Loop or iterate through a hash |
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
| Print a hash |
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
| Remove a key from a hash |
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.
As a note, to delete a key when you have a hash reference you can use either the notation $$hashRef{$key} or $hashRef->{$key}.
back to top
| Sort or order a hash |
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:
v2: 251 v1: 75 v4: 12 v3: 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 <=>.
| Reverse a hash |
Because a hash represents a list of (key, value) pairs, you can reverse such a list and after that each pair will become (value, key). We'll do this by using thereverse 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' => 'Dr. Hook', 'Hide your heart' => 'Bonnie Tyler', 'Romanza' => 'Andrea Bocelli' };If you want to download the Perl hashes script with all the above examples included, please click here: Script download
没有评论:
发表评论