Broad Network


Processing a Perl Hash

Using Perl Hashes – Part 2

Perl Course

Foreword: In this part of the series, I explain how to scan a hash, how to determine the number (length) of entries in a hash, how to look up a hash element by key and how to look up a hash element by value.

By: Chrysanthus Date Published: 3 Nov 2015

Introduction

This is part 2 of my series, Using Perl Hashes. In this part of the series, I explain how to scan a hash, how to determine the number (length) of entries in a hash, how to look up a hash element by key and how to look up a hash element by value. You should have read the previous part of the series before coming here, as this is a continuation.

Scanning a Hash
You can decide to access all the key/value pairs (elements) of a hash. It is simple, use the each function in a while loop as in the following code, which you should read and try:

use strict;

    my %fruitColor = (Apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green", Pineapple =>);

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

I tried the code in my computer and the output was:

    Pear green
    Pineapple
    Banana yellow
    Apple purple
    Lemon green

In the iteration of the hash, the order in which you typed in the elements is not necessarily maintained at the output. Whenever you code a hash, when retrieving it, the order is not necessarily maintained.

In the code, the argument to the each function is the variable of the hash, %fruitColor. In list context (when the return value of the each function is assigned to a list as above) it returns the key and corresponding value as a list (pair), for the next element (beginning with the first in the iteration). In scalar context (when assigned to a scalar), it returns the key of the next element.

In the while condition, since the variables, $key and $value are declared at that position and we are in Perl strict mode, the variables are preceded by the my modifier. (my $key, my $value) is a list that receives the key/value pair from the each() function.

In many situations, you will need just the values of the entries (elements). In this case, the each() function in the while loop is used in scalar context. The keys are then used to get the values. Read and try the following code:

use strict;

    my %fruitColor = (Apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green", Pineapple =>);

    while (my $key = each %fruitColor)
        {
         print "$fruitColor{$key} \n";
        }

I tried the code in my computer and I had,

green
purple
yellow
green


Note that the value for the Pineapple key is undef, which is not printed. Note the complete expression in the while loop condition.

You can scan a hash using sorted keys. The sort() function ordinarily sorts using the order “0-9A-Za-z”. Try the following code:

use strict;

    my %fruitColor = (apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green", Pineapple =>);

    foreach my $key (sort keys %fruitColor)
        {
         print "$fruitColor{$key} \n";
         #other statements
        }

The output is:

yellow
green
green

purple

The output is displayed by sorted keys and not sorted values. The gap in the output is for the value, undef. In the code, the foreach compound statement has been used. The foreach modifier needs a list and that is why you have parentheses around,

    sort keys %fruitColor

Here you have two functions. The keys() function returns a list of keys. The sort() function sorts the list of keys, returning the sorted list. The parentheses ensure that the keys are in a list.

What if you just what to deal with certain keys that fulfill a certain condition? Whenever you hear of obtaining a sub list from a larger list, and the elements of the sub list fulfill a condition, know that you have to use the grep() function. In this case the first argument to the grep function is the condition and the second argument is the larger list.

In the grep function, $_ refers to each element in the larger list. In some cases, $_ is not typed in the condition, but it is effective in the condition. Read and try the following code that prints the values of hash keys that begin with a vowel:

use strict;

    my %fruitColor = (apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green", Pineapple =>);

    foreach my $key (grep /^[aeiou]/i, keys %fruitColor)
        {
         print "$fruitColor{$key} \n";
         #other statements
        }

The output is:

    purple

for the apple key. There are two arguments as usual to the grep() function. The first one is a regex, which works with $_. The argument is equivalent to $_ =~ /^[aeiou]/i . In the code, $_ is implicit, but effective. The second argument is “keys %fruitColor”, which results in all the keys of the hash. So, the second argument to this grep() function is a larger list made up of keys of the hash. $_ for the first argument refers to each key in the second argument. The grep() function returns a sub list of keys, which is the list for the foreach modifier (compound statement). Each item in this sub list is identified by $key.

Determining the Size of a Hash
In this section I explain how to determine the length of a hash and what the length of a hash might mean.

You can use the keys() built-in function in scalar context to find out have many entries (elements) you have in a hash. In a hash, an entry is a key/value pair. In a hash, a key may not have a value (i.e. value is undef), but the key will always be there. So, length of hash can be considered as number of keys. The keys() function returns a list (array) of all the hash keys. If the array of keys is assigned to a scalar variable, you get the number of keys in the array, and hence the hash. Just remember: assigning a list to a scalar will return the last value in the list, while assigning an array will return the number of elements in the array.

Read and try the following code, which gives the number of keys in a hash:

use strict;

    my %fruitColor = (apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green", Pineapple =>);

    my $key_count = keys %fruitColor;

    print $key_count;

The output is:

    5

In the code, the argument to the keys function is, %fruitColor.

Note: the keys() function resets the iterator, so you can have strange results, if you use the keys() function within a loop.

Another interpretation for the length of a hash is the number of defined values. It is possible for the value of some keys to be undef. If you consider the length of a hash to be the number of the defined values (values that are not undef), then the length may be less than the number of keys (number of elements).

To know the number of defined values, you have to test for all the values, using the defined() function. The defined() function returns true if the value is not undef and false if the value is undef. The aim of the grep() function is to return a sub list from a larger list, for each element in the larger list that passes a test condition. So, to obtain the number of defined values, you should use the grep() function, where the first argument is the defined function and the second argument is a list of all the values in the hash. You obtain all the values of the hash using the values() function. The following code illustrates this:

use strict;

    my %fruitColor = (apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green", Pineapple =>);

    my $defined_value_count = grep { defined } values %fruitColor;

    print $defined_value_count;

The output is,

    4

The second argument to the grep() function is a block. The defined() function in the block, works with $_, which refers to each value in the larger list.

Looking up a hash Element by Key
Looking up a hash element by key, is simple: use the exists() function. The argument to the exists() function is the assumed key of the hash. If the key (element) is present, then the exists() function returns true, otherwise it returns false. Try the following code:

use strict;

    my %fruitColor = (apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green", Pineapple =>);

    print "Key with Banana is present.\n" if exists($fruitColor{Banana});

    print "Key with Orange is present.\n" if exists($fruitColor{Orange});

The output is:

    Key with Banana is present.

The second print does not take place because there is no key with “Orange”.

Looking up a Hash Element by Value
The keys of a hash are always unique. However, different keys may have the same value. You can search a hash by value, copying all the found values and their keys into another small hash. The following code illustrates this, using a while loop and the each() function:

use strict;

    my %found;

    my %fruitColor = (apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green", Pineapple =>);

    while (my ($key, $value) = each %fruitColor)
        {
            $found{$key} = $value if $fruitColor{$key} eq "green";
        }

    print "$_ " foreach %found;

In my computer the output was,

    Pear green Lemon green

Two elements were found with the same value but different keys.

In the code, the each() function returns the key/value pair for each iteration. The value, we are looking for, in the hash is “green”. In the while loop there is a simple if statement. The condition for the if statement is ($fruitColor{$key} eq "green"). If a key has value, “green” then the key and the value are added to the %found hash. The expression, “$found{$key} = $value” creates a key and assigns a value at the same time. The last statement in the code prints all the items in the %found hash, separating them with a space.

That is it for this part of the series. We stop here and continue in the next part.

Chrys

Related Links

Perl Basics
Perl Data Types
Perl Syntax
Perl References Optimized
Handling Files and Directories in Perl
Perl Function
Perl Package
Perl Object Oriented Programming
Perl Regular Expressions
Perl Operators
Perl Core Number Basics and Testing
Commonly Used Perl Predefined Functions
Line Oriented Operator and Here-doc
Handling Strings in Perl
Using Perl Arrays
Using Perl Hashes
Perl Multi-Dimensional Array
Date and Time in Perl
Perl Scoping
Namespace in Perl
Perl Eval Function
Writing a Perl Command Line Tool
Perl Insecurities and Prevention
Sending Email with Perl
Advanced Course
Miscellaneous Features in Perl
Perl Two-Dimensional Structures
Advanced Perl Regular Expressions
Designing and Using a Perl Module
More Related Links
Perl Mailsend
PurePerl MySQL API
Perl Course - Professional and Advanced
Major in Website Design
Web Development Course
Producing a Pure Perl Library
MySQL Course

BACK NEXT

Comments

Become the Writer's Fan
Send the Writer a Message