Last Updated:

Working with hashes in Perl

hashes in Perl
The translation is quite free. Comments and suggestions leave in the form of comments, at the bottom of the page

 

  • Initializing (clearing) the hash
  • Add a key/value pair to a hash
  • Add multiple key/value pairs to a hash
  • Copy hashes
  • Delete a single key/value pair
  • Iterate through all key/value pairs
  • Get the hash size
  • Using hash pointers
  • Function that builds a hash from hashes and returns a pointer to the hash
  • Access the hash from hashes using pointers. Output values
  • Function that builds a hash from hashes from hashes and returns a pointer to the hash
  • Access hashes from hashes from hashes using pointers. Display values.
  • Output keys and values from a hash obtained by a pointer
  • Determining whether a value exists in a hash

The author of the article does not give any guarantees that the code given in it, being "converted" with the help of Copy/Past, will work. All examples worked at the time of writing.

 

Initializing (clearing) the hash

The fastest way to clear is to assign an empty list.

Realization

    my %hash = ();

Note

It is often asked how to initialize a pointer to a hash (hash ref). A pointer is a scalar variable and it is initialized accordingly. For example:

    my $hash_ref;
    my $hash_ref = 0;  # zero

 

Add a key/value pair to a hash

In the examples below, quotation marks around keys can be omitted if the keys are identifiers.

Hash:

Decision

$hash{ 'key' } = 'value'; # hash

     $hash{ $key } = $value; # hash, using a variable

Hash pointer:

Decision

    $href->{ 'key' } = 'value'; # pointer to hash

     $href->{ $key } = $value; # pointer to hash, using a variable

 

Add multiple key/value pairs to a hash

Decision

These operations are equivalent, just the second one is more readable.

    %hash = ( 'key1', 'value1', 'key2', 'value2', 'key3', 'value3' );

    %hash = (
        key1 => 'value1',
        key2 => 'value2',
        key3 => 'value3',
    );

 

Copy hashes

Decision

my %hash_copy = %hash; # copy hash

my $href_copy = $href; # copy the pointer to the hash

 

Delete a single key/value pair

Although deleting a hash and deleting a hash pointer are different operations, both of which are performed using the delete function.

Decision

Hash:

    delete $hash{$key};

Hash pointer:

    delete $hash_ref->{$key};

 

Iterate through all key/value pairs

The example below prints all key/value pairs.

Decision

Use the each function with a while loop. Note that each will iterate through the pairs in a random order, but the order will be the same as the search using the keys and values functions.

    while ( my ($key, $value) = each(%hash) ) {
        print "$key => $value\n";
    }

For a hash pointer, a slight difference:

    while ( my ($key, $value) = each(%$hash_ref) ) {
        print "$key => $value\n";
    }

Decision

Using the keys function with a for loop

    for my $key ( keys %hash ) {
        my $value = $hash{$key};
        print "$key => $value\n";
    }

Example

    my $file = $ARGV[0] || "-";

    my %from = ();

    open FILE, "< $file" or die "Can't open $file : $!";

    while( <FILE> ) {
        if (/^From: (.*)/) { $from{$1}++ }  # count repeat sender
    } close FILE; for my $sender ( sort keys %from ) { print "$sender: $from{$sender}\n"; }

 

Get the hash size

Decision

    print "size of hash:  " . keys( %hash ) . ".\n";

Solution

   my $i = 0;

     $i += scalar keys %$hash_ref; # method 1: explicit scalar context
     $i += keys %$hash_ref; # method 2: implicit scalar context

 

Using hash pointers

Decision

   subfoo
     {
         my $hash_ref;

         $hash_ref->{ 'key1' } = 'value1';
         $hash_ref->{ 'key2' } = 'value2';
         $hash_ref->{ 'key3' } = 'value3';

         return $hash_ref;
     }

     my $hash_ref = foo();

     print "keys...", sort keys %$hash_ref, "...\n";

 

Function that builds a hash from hashes and returns a pointer to the hash

Decision

    sub foo
    {
        my ( $login, $p, $uid, $gid, $gecos, $dir, $s );

        my %HoH = ();

        my $file = '/etc/passwd';
        open( PASSWD, "< $file" ) or die "Can't open $file : $!";

        while( <PASSWD> ) {
            ( $login, $p, $uid, $gid, $gecos, $dir, $s ) = split( ':' );

            $HoH{ $login }{ 'uid' } = $uid;
            $HoH{ $login }{ 'gid' } = $gid;
            $HoH{ $login }{ 'dir' } = $dir;
        }

        close PASSWD;

        return \%HoH;
    }

 

Access the hash from hashes using pointers. Output values

Decision

    my $rHoH = foo();

     my( $uid, $gid, $dir );

     for my $login ( keys %$rHoH ) {

         $uid = $rHoH->{ $login }->{ 'uid' }; # method 1. More readable
         $gid = ${ $rHoH->{ $login } }{ 'gid' }; # method 2
         $dir = ${ ${ $rHoH }{ $login } }{ 'dir' }; # method 3. Less readable

         print "uid: $uid, gid: $gid, dir, $dir.\n";
     }

Decision

    my $rHoH = foo();

    for my $k1 ( sort keys %$rHoH ) {
        print "k1: $k1\n";
        for my $k2 ( keys %{$rHoH->{ $k1 }} ) {
            print "k2: $k2 $rHoH->{ $k1 }{ $k2 }\n";
        }
    }

 

Function that builds a hash from hashes from hashes and returns a pointer to the hash

Decision

    sub foo
    {
        my %HoHoH = ();

        while( ... ) {

            if( /LOCATION:/ ) {

                ...

            } elsif( /MODULE:/ ) {

                $HoHoH{ $loc }{ $module_type }{ MODULE_NAME } = $module_name;

            } elsif( $ARGS_ALLOWED ) {

                $HoHoH{ $loc }{ $module_type }{ $arg_name } = $arg_value;

            }

        }

        return \%HoHoH;
    }

 

Access hashes from hashes from hashes using pointers. Display values.

Decision

    my $rHoH = foo();

    for my $k1 ( sort keys %$rHoHoH ) {
        print "$k1\n";

        for my $k2 ( sort keys %{$rHoHoH->{ $k1 }} ) {
            print "\t$k2\n";

            for my $k3 ( sort keys %{$rHoHoH->{ $k1 }->{ $k2 }} ) {
                print "\t\t$k3 => $rHoHoH->{ $k1 }->{ $k2 }->{ $k3 }\n";
            }
        }
    }

 

Output keys and values from a hash obtained by a pointer

Decision

 while( my ($k, $v) = each %$hash_ref ) {
         print "key: $k, value: $v.\n";
     }

 

Determining whether a value exists in a hash

Decision

  print "Value EXISTS, but may not be defined.\n"
if exists $hash{ $key };

     print "Value is DEFINED, but may be false.\n"
if defined $hash{ $key };

     print "Value TRUE\n"
if $hash{ $key };

Example

Let's say we run a SQL query that can return records that contain a null value. Before using the query result, we need to check whether the values obtained are DEFINED. Note that the function connects to the database server, prepares the query, executes it, and gets a pointer to the hash using the DBI function. sql_fetch_hashref()fetchrow_hashref()

    my $answers = 'a,b,c,d,e';

    my $sql = "select max_time, $answers from questions " .
              'where question_number=?';
    my $hash_ref = sql_fetch_hashref( $sql, $q );

    my @answers = split ',', $answers;

    my $max_time = $hash_ref->{max_time} || '60';

    my $hash_ref_ans;
    for my $letter ( @answers ) {
        $hash_ref_ans->{ $letter } = $hash_ref->{ $letter }
            if defined $hash_ref->{ $letter };
    }

The for loop generates a hash only with SPECIFIC key/value pairs.