Hashes in Perl

Hashes are the third and final type of variable we can use to store and manipulate our data. A hash is also known as an associative array because it can be seen as an advanced and twisted version of the arrays you learned about earlier. A hash is like an array list by the way it holds a list full of information, but the difference is how the data is stored and how it’s retrieved.

We store hash information using KEY/VALUE pairs, you can forget about the numeric indexing you learned about while using arrays. If you don’t know what index “marshmallow” is in an array of 30,000 elements, don’t worry, you’ll see easier ways to retrieve all kinds of data using this new data structure.

We use % to associate with hashes, but like everything else, it shares the $ when you refer to a single value. To make a hash, you have to be sure to set up two bits of information. The KEY and the VALUE. Using arrays, the array name itself acted as the key, under hashes you have to create your own.

@colors = (“red”, “brown”, “purple”, “pink”);

The array @colors is a list containing the values red, brown, purple and pink. @colors acts as the key in the sense that all of the data (color names) are connected and retrieved from it. For example, if you remember how we retrieved array elements from the previous chaper..

print $colors[0];

As you can see, all the indexes are literally tied with the name @colors or @array.


Creating your first hash

my %hash = (“Fred Flintstone” => “Wilma Flintstone”);

We just made our first hash with the key Fred Flintsone and the value Wilma Flintstone. They key is always the first item in the key/value pair, or the key is ALWAYS on the left. There are a few other ways of setting up the same hash:

my %hash = (“Fred Flintstone” , “Wilma Flintstone”);

my %hash = qw(Fred_Flinstone Wilma_Flintstone);

These are just two of the other methods you can use to create your hash. Please take note that the first and second example are identical. The => in Perl represents a literal comma (,). Some programmers prefer this over using the comma because => stands out which makes it easier to see which piece is the key and which is the value. Because it’s easier to see, this tutorial will primarily be using this method.

In most cases, Perl ignores whitespace except when it’s in a double quoted string. You’ll find most programmers setting up a hash looking like the one below. Because Perl ignores the whitespace, the programmer is given the choice to write the code in a format they like and understand.

my %food = (
“warm” => “oatmeal”,
“hot”    => “steak”,
“cold”  =>  “ice cream”
);

As we just learned, white spaces aren’t important so we aligned our data in a one-per row, comma separated list.  If you payed close enough attention, you’d notice that the last item in our hash does not have a comma after it.  Commas are required between each item and are not to be used after the last one.

If remember this layout is too much to remember at this point, you can write them like you would an array.  You would write each key/value pair as normal on the same line, separated by commas.

my %food = (“warm” => “oatmeal” , “hot” => “steak”, “cold” => “ice cream”);

But as you can probably see from that, it’s more difficult to see each key/value pair since everything is bunched up like that.  Just remember, it’s all a preference to the coder.  Do whatever is easier for you to understand.
Printing hashes

You can retrieve the value of a hash key by calling it’s key name inside the brackets of $hash{}.  For example, using the same %food we made earlier, we want to print out the value “steak”.  Since steak is tied to the key (to the left of =>) “hot”, we would write something like this:

print $food{“hot”};

From our code, we can see “hot” => “steak”, so naturally the print statement above prints the word steak.  If we used print $food{“cold”}, it would have returned the value ice cream.

Printing the entire hash can be a little difficult for someone just beginning in Perl.  You could, if you didn’t care of the format, print %hash; and use the results.  The problem with this method is there aren’t any spaces between any of the keys or values.  If you printed %food like that, the result would be one1two2.  Not very handy, is it?

The quickest way to print a complete hash is tossing it into a foreach loop.  A foreach loop iterates (passes over) each element and applies whatever command you want.  This looping structure is not within this tutorial’s guidlines, so we’re not going into great detail about it at this point.  In the example below, we are passing over every key/value pair in

foreach(keys %hash)
{
print “$_ => $hash{$_}\n”;
}

Let’s discuss this line by line.  We begin the foreach loop foreach() telling it to iterate over each keys in the %hash.  Remember, a key is the first item in a key/value pair.  So, for every key it passes in %hash, it will apply whatever we set in our brackets {}.

$_ is a special variable used by Perl to store information temporarily.  Each time it comes across another key, it’s data is stored in $_.  The first thing that iterates in our hash would be “warm” => “oatmeal”, warm will be stored inside of $_ until your print is done and it moves onto the next.

Remember, => in this case isn’t a comma.  If it’s used inside a set of quotations, it prints exactly as it looks: =>.   Now we move on to $hash{$_}.  Here we see the special $_ variable again, this means the information that was currently stored in $_ is now deleted and is now being used to keep our new data.  If $_ is they hash key, $hash{$_} is the hash value.

The \n at the end is the linefeed character, it acts the same way as the <br> tags do in HTML.  Putting it at the end of the line means it will print one key/one value per line.  Here is an example.

my %weather = (
“yesterday” => “cold”,
“today”        => “snowy”,
“tomorrow   => “tropic”
);

foreach(keys %weather)
{
print “$_ => $weather{$_};
}

Adding to a hash

Adding information into a hash is much easier than adding data into an array, and in many ways it’s a lot more efficient.  You no longer have to worry on how many indexes you have, you don’t have to count anymore, all you do is pass another key/value to the hash.

$hash{$key} = $value;

Let’s make an hash using the first name as the key and the last name as the value.  Then we realize we forgot our little friend Santa Clause, and just so we’re sure we don’t get coal next Christmas, we decide to add his name for good graces.

my %names = (
“Frosty”  => “Snowman”,
“Easter”  => “Bunny”,
“Big”      => “Bird”
);

$names{‘Santa’} = “Claus”;
We setup a hash as we’ve already done a few times before, try to visualize and memorize the code and setup the best you can.  It may be a little difficult at first, but after practicing by setting up your own hashes, you’ll get it down.

Since we are adding one string (key/value), we call names with it’s scalar $ symbol.  Remember, the key comes before the value so we’re setting “Santa” => “Claus”.  Don’t forget to use your tick marks surrounding your key.  As another example, let’s add the name Static Shock.

$names{‘Static’} = “Shock”;

Our hash now contains Frosty => Snowman , Easter => Bunny, Big => Bird and Santa Clause.  Though they may not be in that order.

One thing to keep in mind is you better make sure each and every one of your keys are unique.  You cannot use $name{‘Fred’} = “Fintstone” and $name{‘Fred’} = “Bush” in the same hash, otherwise only one of the two will be used correctly and the other one will be ignored (to be more technical, the one that appears is the last pair that shares a common key.  In this case, Fred => Bush would be read, Fred Flinstone will be over-written.


Deleting hash pairs

Deleting items from a hash is not much different than adding things to them. We call the delete method on the hash key.  Since the key and value are paired together, by deleting the key you are actually removing the key/value pair.

delete $hash{$key};

From our last example, it turns out our parents told us the Easter Bunny isn’t real 🙁 So we may as well remove him from our list.

delete $hash{‘Easter’};

The value Bunny is connected to Easter, so they are both permanently removed.  The next time you load the script, this pair will be gone, so beware.

If you try to delete a key that doesn’t exist, nothing happens.  Obviously it won’t delete it if it can’t find the exact key you’re looking for, but it won’t give you an error saying it didn’t exist either. (not until the next section when we talk about existance).

Let’s setup a new hash and remove whichever key you want. In my example, we are removing Cake since we don’t need two snacks before dinner.

my %food = (
“Snickers”  => “chocolate”,
“Cake”       => “angel food”,
“Steak”      => “meat”
);
delete $food{‘Cake’};

Testing for existance

One thing you’ll find yourself having to do over and over again when using hashes is testing to see if a certain key exists.  This is easily done by using an if/else iteration.  We have not gone over any looping structures yet and this is the best one to start out with.

If/Else will read the parameters you are testing, and if it proves to be what you are testing for, it will do whatever you tell it to in the first set of {} brackets.  If for any reason the test didn’t go successful, the else is activated and the code between the last set of {} is activated.

if (test)
{run this code if our test passes}
else
{run whatever is in here if it fails}

That is a naked If/Else.  Following the if is where you are set up your test. The test can be virtually anything you want to test against, but for this chapter we’re only going to be learning how to test for the existance of hash elements.

Exist is the method we use to test the existance of a key in a hash.  Perl is pretty consistant when it comes to naming their methods which makes them a lot easier to remember and on occasion, easier to guess.

if(exists $hash{$key})
{ if the hash key exists, this will run}
else
{if this section is activated, it means $hash{$key} doesn’t exist)

if() is where our test begins.  We are testing for exists $hash{$key}.  If it exists, our first set of {} is activated and used and if it doesn’t exist, the second set does.

Let’s try a real example now:

my %pop = (
“Mello Yello”     => “good”,
“Pepsi”               => “nasty”,
“Mountain Dew” => “pure as gold”
);

if (exists $pop{‘Pepsi’})
{ print “Yes, Pepsi exists!”; }
else
{ print “No, Pepsi doesn’t exist”; }

We are testing for the existance of the key Pepsi.  If you made the same hash as the example, you will notice we DO infact have a key called ‘Pepsi’.  That means if you run this script, the first set of {} will be used and the print statement “Yes, Pepsi exists!” will show on your screen.

if (exists $pop{‘Vanilla Coke’})
{ print “Yes, Vanilla Coke exists!”; }
else
{ print “No, Vanilla Coke doesn’t exist”; }

Now, if you run this on your website or through the command prompt using the same %pop we made a minute ago, the ELSE is activated because we never made the key Vanilla Coke.

Like we discussed earlier, you can do whatever you want inside the {} brackets, all we did in the last two examples was print a little message to the screen.  But what would we do if we wanted to see if a key exists, and if it does, delete it?

That’s simple:

my %pop = (
“Mello Yello”     => “good”,
“Pepsi”               => “nasty”,
“Mountain Dew” => “pure as gold”
);

if (exists $pop{‘Pepsi’})
{ delete $pop{‘Pepsi’}; }
else
{ print “No, Pepsi doesn’t exist”; }

That might be a little confusing at a first glance, as you can see we are using quite a few {} brackets.  All we did was replace the print statement “Yes it exists” from the last example with the delete method as you learned earlier.  If you run this script, it will find Pepsi and delete it for you.


Reversing Keys and Values

It has been said that you can’t consider yourself a hash expert unless you know how to remap your hash in such a way all your keys become values and all your values become keys. To be honest with you, I don’t see any logical reason anyone would do something like this and I have never used this before in my life.

my %names = (
“Bill”  =>  “Nye”,
“Bart” => “Simpson”,
“Buffy” => “Slayer”
);

my %reversed_names = reverse %names;

foreach(keys %reversed_names) {
print “$_ => $reversed_names{$_}\n”;
}

The new hash name can be whatever you want to call it, %reversed_names isn’t a built-in function.  You could have called it %newhash and it would work exactly the same.

We first create a new hash and call it whatever you want, we then use the reverse command on the %hash we want to reverse the keys and values for.  Since we are assigning the reversed hash to a different hash all together, the original is not affected.

After running that code in your window, the results will be something like:

Nye => Bill
Simpson => Bart
Slayer => Buffy

Notice how the first names are now following the last.  The last names are now the keys and the first names were turned into the values.


The merging of hashes

Sometimes you will want to merge two or more different hashes into one large hash. This is done using a simple hash assignment.

my %bighash = (%hash1, %hash2);

%bighash now contains each key and value pair from both hash1 and hash2.  Since hashes are not stored in any specific order (technically it is, Perl orders them in a way it can read them more efficiently.  But for our sake, it’s pretty much random).

my %names1 = (
“Bill”  =>  “Nye”,
“Bart” => “Simpson”,
“Buffy” => “Slayer”
);

my %names2 = (
“Fred”  =>  “Flinstone”,
“Dino” => “Flinstone”,
“Xena” => “Princess”
);

my %newnames = (%names1, %names2);
Our %newnames now contain all six key/value pairs like you would expect.


Sorting your hash

There is no way you can know which order your hashes will print in by default, and chances are when you’re messing with a fair amount of data you will want to sort them out in one fashion or another.

We can sort hashes alpha-numerically by using the sort method as we’ve seen in some of the earlier tutorials.   The sort will iterate through each element in your list and put them in order by keys, this is very impressive when you can sort hundreds of thousands of element entries in a few seconds.

foreach (sort keys %hash)
{
….
}

We have to use the foreach looping structure again, this way perl can read every key/value pair that’s stored in our hash.  Next we call sort on our keys from %hash.  Think of it as saying “SORT the KEYS of %HASH” and it makes logical sense, it wouldn’t make sense saying “Keys the SORT of %HASH”.  Hopefully that will help you remember which order they go in.

my %music = (
” Ride of your life” => “John Gregory”,
“Kiss Me”                => “Sixpense None The Richer”,
“Superman”            => “Five For Fighting”
);

foreach (sort keys %music)
{
print “$_ => $music{$_}\n”;
}

results:
Kiss Me => Sixpense None The Richer
Ride of your life => John Gregory
Superman => Five For Fighting

This will sort alphanumberically giving numerics first, meaning if any of your hash keys begin with a number, they’ll appear before the rest of them.   But as you can see from the example I used used from the above, it alphabetized the names of the songs for me.

Sometimes you want to sort your hash backwards printing in reverse alpha-numeric order.   We do this by using the reverse method on our sort block and perl will rebuild the hash backwards for you.

foreach (reverse sort keys %hash)
{
….
}

The only difference between this and our last sort is the reverse which is called before sort.  This also makes sense in English when read as “REVERSE the SORTed KEYS of %HASH”.   Using the same example as we did with our songs above, this is how you would get them to print backwards according to key.
my %music = (
” Ride of your life” => “John Gregory”,
“Kiss Me”                => “Sixpense None The Richer”,
“Superman”            => “Five For Fighting”
);

foreach (reverse sort keys %music)
{
print “$_ => $music{$_}\n”;
}

results:
Superman => Five For Fighting
Ride of your life => John Gregory
Kiss Me => Sixpense None The Richer

As you can see our list was placed in reverse-alpha-numeric order for us.   Try to memorize which order reverse, sort and keys go in.  The order will always go REVERSE then SORT then KEYS then the hash.

Author: Syperder Co
I waltzed into the Web Design community as a professional when I was just 15 years of age founding SpyderWebDesigns. Through the years my interests shifted from web development to backbone and user interaction.In 2000 Sulfericacid.com was born. The world’s largest free and 100% ad-free web site where you could use and download 24 Perl and CGI script along with tutorials without limits or restrictions. January 2005 the site was renamed to SpyderScripts.com as a subsidy of SpyderCo.

In 2001 I also founded an SEO company SpyderSubmission.com. We’ve helped nearly 2300 web sites achieve higher rankings than they ever could have imagined since our launch four years ago.

On a more personal note, I’ve attained 28 certifications from BrainBench.com and about 40 certifications in total from all resources. One of these is a near Masters in Perl which ranks second highest test score in the state and 17th throughout the country.

I have a Perl Abbot status on PerlMonks.org working on getting my Perl Saint status this fall.