Web Development

Using hash variables in Perl

In Perl, a hash lets you create a one-to-one association between a variable, called the key, and a value. We'll show you the basics of Perl hashes and some useful tricks.

One of the most useful constructs in Perl is the humble array, which lets you store more than one value in a single variable. This is very useful if you have a set of related values—for example, a shopping list—and you need to group them into a collection, yet be able to access them individually.

A variant of the regular array, which is indexed by number, is the hash or associative array, which is indexed by key. A hash is a Perl construct that allows a programmer to create one-to-one associations between a variable, or "key," and its value. Elements of a hash can be accessed only via their keys, and keys within a hash must be unique.

Get ready, because we're about to give you a crash course in how Perl hashes work. And we'll show you some examples of where you can use them.

Hash basics
Creating a Perl hash is very similar to defining an array: You create a hash variable and (optionally) assign some keys and values to it:
# define hash
%account = ('username' => 'jimmyboy', 'password' => 'scar3me');

Notice the % symbol preceding the variable name, and contrast it to the @ sign preceding an array. Notice also the => symbol, which is used to connect a key to its associated value.

Hash elements consist of a key-value pair. Each key in a hash is unique and serves as a unique identifier for the corresponding value. The value can be retrieved only if you know the corresponding key. Therefore, in the example above, you would retrieve the value jimmyboy with the following notation:
# retrieve value of hash element
print $account{'username'};

To add new elements to a hash, define a new key-value pair, and Perl will automatically add it to the hash variable:
# add an element to a hash
$account{'active'} = 1;
 
# the hash now contains
%account = ('username' => 'jimmyboy', 'password' => 'scar3me', 'active' => 1);

Note that unlike arrays, Perl hashes are not arranged in any specific numerical order or in the order in which the keys are added. Rather, Perl uses its own sorting algorithms to arrange the elements in an optimal manner. For this reason, you must always access hash values by key rather than position.

To remove an element from a hash, use the delete() function as shown below. Don't even think about using the infamous—and flawed—technique of assigning an empty value to the key. That just leaves the key in the array with a null value. It doesn't actually remove the key, which is why you need to use delete() instead.
# delete the named key from the hash
delete($account{'password'});

Hashes and regular arrays mix well with each other, so it's even possible to have a hash key pointing to an array (or vice versa), as in this example:
# hash keys pointing to an array
%combo = ('colors' => ['red', 'green', 'blue'], 'vowels' => ['a', 'e', 'i', 'o', 'u']);

Processing hash elements
Perl offers the keys() and values() functions to obtain lists of all the keys and values present in a hash. These functions come in handy when you need to process all the elements in a hash using a foreach() loop. The following example iterates over a hash and writes the elements to a file as comma-separated key-value pairs.
# set up hash
%capitals = ('china' => 'beijing', 'england' => 'london', 'france' => 'paris', 'norway' => 'oslo', 'italy' => 'rome');
 
# open file
open (FILE, ">data.txt");
 
# process hash elements
# write to file in csv format
foreach $k (keys (%capitals))
{
        print FILE $k, ",", $capitals{$k}, "\n";
}
 
# close file
close(FILE);

Note that the keys() function returns an array. By iterating over this array in a foreach() loop, it becomes possible to process each and every element in the hash.

Another option is to use the each() function, which iteratively moves through a hash creating a two-item array at each stage for the current key and value. The each() function is thus well suited to a while() loop, as illustrated in this rewrite of the previous example:
# set up hash
%capitals = ('china' => 'beijing', 'england' => 'london', 'france' => 'paris', 'norway' => 'oslo', 'italy' => 'rome');
 
# open file
open (FILE, ">data.txt");
 
# process hash elements
# write to file in csv format
while ( ($country, $capital) = each (%capitals))
{
       print FILE $country, ",", $capital, "\n";
}
 
# close file
close(FILE);

Quick tip: If all you really want to do is check if a particular value exists in a hash, don't waste time by using a loop and an if() test at each iteration. Instead, use the built-in exists() function, which returns Boolean true if a key match occurs.

Using hash variables in forms
Most Web forms consist of a series of input controls, each with a unique name and each holding a user-provided value. Since a hash is designed to store variable-value pairs, it serves as a handy storage container for form data. To illustrate, consider the following form:
<html>
<head></head>
<body>
 
<form action="/cgi-bin/handler.cgi" method="post">
Enter a value for x:
<br>
<input type="text" name="x">
 
<p>
 
Enter a value for y:
<br>
<input type="text" name="y">
 
<p>
 
<input type="submit" name="Calculate">
</form>
 
</body>
</html>

This form passes a set of variable-value pairs to the script handler.cgi via the POST method. The data entered by the user is passed to the CGI script as a string of encoded values; the CGI script needs to decompose the string into its individual key-value pairs and assign them to a hash for further processing. Here is how it works:
#!/usr/bin/perl
 
# use CGI.pm
use CGI qw(:standard);
 
# print header
print header();
 
# read form data into hash
$query = new CGI;
%data = $query->Vars();
 
# get values from hash
# use them in a calculation
print $data{'x'}, " x ", $data{'y'}, " = ", $data{'x'} * $data{'y'};

When a user submits the form to the CGI script above, the CGI.pm module's Vars() method reads the data submitted and converts it into a series of variable-value pairs within the %data hash. The values can then be accessed using the corresponding hash key.

Using hash variables for configuration data
Another common use of hash variables is to store information (such as application configuration variables) in an easily accessible manner, and make it available to other callers in a program. As an example, consider the following program, which asks for user input for configuration values and then stores those values in a hash. The configuration hash is accessible to other subroutines within the program and can thus be used to retrieve the current state at any time (see Listing A).

Here, the program keeps asking the user to choose an option from the menu of choices. Depending on the menu choice selected, the value entered by the user at the prompt is connected to the appropriate hash key. The set_config() routine takes care of actually updating the hash, while the print_config() routine iterates over the hash, reading and displaying the values within it.

As you can see, Perl hashes can be used in a variety of different places, and are easily one of the most useful constructs in the Perl universe. Play with them a little, and you'll soon find yourself familiar enough with them to begin using them in your scripts!
0 comments

Editor's Picks