#!/usr/bin/perl -w
# To the student:
#
# This tutorial has been written given the assumption that you
# are familiar with what a hash is and what some of the hash
# oriented functions are. It is NOT written to teach you how
# to use a hash in it's most basic form! If you need help with
# that, refer to Perl's documentation or your instructor's
# notes.
#
# Every attempt has been made to ensure that the information
# presented in this code example is correct and syntactically
# valid. You can yank and paste this code into your text editor
# and run it directly on your own machine. Please report any
# errors to kaiw@voyager.deanza.edu
#
# ~Kai
#
################# THREE BASIC USES OF HASHES ####################
#
# First, let's review what a hash actually is. Functionally,
# it is equivalent to an orderless array. Data in a hash can be
# accessed when provided with a particular index. This index is
# called a KEY. Each key is associated with a particular value,
# setting up what is called a key/value pair.
#
# NOTE: A key cannot have more than one value, nor can the same
# key modify two values at the same time!
#
# Just like a phone book has a name which then corresponds to
# a phone number, a hash has a key associated to a value. Now
# that we have the basic uses of hashes down, lets see when
# you as the Perl programmer would want to use one:
############ SITUATION 1: TEXT INDEXING ###########
#
# Let's say we want to store some bank sums from different people
# into some sort of a usable structure. We could set up two
# parallel lists, one with their names, the second with their
# corresponding bank balances in the matching index. So
# Mr. Andresen has a balance of $10,000.00 and
# Ms. Skougaard has a paltry balance of $20.00.
my ( @names, @balances );
@names = ( "Andresen", "Agarwal", "Nguyen", "Skougaard" );
@balances = ( 10000.00 , 15000.00 , 8000.00 , 20.00 );
# Print the balances
print "Current Balances (from lists):\n";
foreach $i ( 0..@names-1 ) ## Note: without the random -1, we would
{ ## run off by one!
print "$names[$i]: $balances[$i]\n";
}
# Increase Mrs. Skougaard's balance by $10,000
# First locate her index
$i = 0; # Reset i's value to zero.
foreach $name ( @names )
{
last if $name =~ /Skougaard/; ## Yuck. Seriously don't do this.
$i++;
}
$balances[$i] += 10000.00; # Now update her balance
# We see with an arrangement like this the data can certainly be
# represented in memory, but not very effectively. To print the
# values, you would have to index through each array, which can
# be quite tedious. In addition, both lists would have to be
# maintained in parallel! This introduces the possibilities for
# off-by-one errors, not to mention it makes NO use of Perl's
# basic constructs like standard list traversal.
#
### BRING IN THE HASH ###
#
# Instead of the awful (but functional example above, let's try
# this intead:
my %bankBalances;
## "key" => "value"
%balances = ( "Andresen" => 10000.00,
"Agarwal" => 15000.00,
"Nguyen" => 8000.00,
"Skougaard"=> 20.00 );
# Print the balances
print "\nCurrent Balances (from hash):\n";
foreach $name ( sort keys %balances )
{
print "$name: $balances{$name}\n";
}
# Increase Mrs. Skougaard's balance by $10,000
$balances{ "Skougaard" } += 10000.00; # That's it!
# Look at how much cleaner and easier this is to manage! We
# can easily print the hash and access the hash data! The
# keys function gets the "keys" to the values, and sort
# simply puts those keys in a default order.
#
# One thing to note: You can NOT perform sequential data
# processing with a hash, as a hash is inherently unordered!
# So when you're using the keys function, unless they're
# sorted, the hash keys will come in RANDOM ORDER! This also
# means that you cannot use list oriented functions directly
# on the hash itself. However, there are still nifty things
# to do with hashes and list oriented functions. More on
# that in a different tutorial.
############ SITUATION 2: COUNTING ###########
#
# Perhaps we have more data we need to process for these
# fine people. Let us imagine that they are with
# Bank of America and BofA leverages a 20 cent charge for
# each time they use their debit card. We'll say that each
# time they charge onto debit, their name gets pushed onto
# a list, and we want to count how many times one person
# charged.
@charges = ( "Andresen","Agarwal","Agarwal","Agarwal","Andresen","Agarwal" );
# I don't even want to think of how to count this with a
# list. In fact, it's a waste of time for you to even think
# about how to do it with a list. It, again, would require
# a parallel list mess and would suck down compute time.
# Lets use a hash instead!
my %chargeCounter;
foreach $person ( @charges )
{
$chargeCounter{$person}++;
}
print "\nCharge count:\n";
foreach $person ( sort keys %chargeCounter )
{
print "$person charged $chargeCounter{$person} times.\n";
}
# As we can see, this makes use of the basic Perl rule that
# the first time you use a value it is auto-initialised to
# undefined (zero in a numeric context)! This quickly counts
# the names in the array!
############ SITUATION 3: DUPLICATE CHECKING AND FILTERING ############
#
# For this third and final task we are going to weed duplicates out of
# an array. There can be many situations where you need to do this.
# This is really just a logical extension from above. So to extend off
# the situational example above, we'll say there's a charge list, but
# now we're tasked with charging each person who has used their debit
# card ONE OR MORE TIMES the standard Bank of America fee of $5.00. We
# are not evil so therefore don't want to charge them $5.00 for each
# use DO WE?
#
# No, so let us filter out the duplicates from the same list:
@charges = ( "Andresen","Agarwal","Agarwal","Agarwal","Andresen","Agarwal" );
my %debitUsed;
foreach $person ( @charges )
{
$debitUsed{$person} = 1; ## NOTE: this is almost identical to above!
## In fact, you'll see soon that we can really
## use the same hash from above for duplicate
## checking.
}
@chargeThesePeople = keys %debitUsed;
print "\nCharge these people \$5.00: @chargeThesePeople\n";
# Notice, if we want to, we can easily use this hash in a boolean/integer
# context. Any value that is not undefined is true, so it makes it simple
# to do these if tests:
if ( $debitUsed{"Andresen"} ) { print "Andresen used his debit card.\n" }
else { print "Andresen did NOT use his debit card.\n" }
if ( $debitUsed{"Skougaard"} ) { print "Skougaard used her debit card.\n" }
else { print "Skougaard did NOT use her debit card.\n" }
##################### IN CLOSING ##########################
#
# As you can see, hashes are a very powerful part of Perl. This
# is again only some of the BASIC usages of hashing. There are
# many more advanced techniques that can be employed. I invite
# you all to share with me any other ways you might have
# used a Perl hash.