Broad Network


Perl Hash of Arrays for Spreadsheet

Perl Two-Dimensional Structures – Part 1

Foreword: In this part of the series, I talk about hash of arrays for a spreadsheet in Perl. A hash-of-arrays is a 2D structure

By: Chrysanthus Date Published: 2 Apr 2016

Introduction

This is part 1 of my series, Perl Two-Dimensional Structures. A Perl 2D structure is created from Perl 1D structures. An array alone is a 1D structure. A hash alone is a 1D structure. In this part of the series, I talk about hash of arrays for a spreadsheet in Perl. A hash-of-arrays is a 2D structure. You should have read the previous parts of the series before reaching here; this is a continuation. An example of a spreadsheet is the Microsoft Excel Sheet. A Perl data structure is a combination of arrays and hashes. In this tutorial I talk about the 2D hash-of-arrays structure.

Pre-knowledge
At the bottom of this page, you will find links to the different series you should have read before coming here, in order to better understand this one.

Example Content
Imagine a class of students, who have written a number of tests. A spreadsheet for the class is something like,

Header             Geography History Physics Math
Joan Mary        50              64         14         85
John Smith       78              20         85         55
Suzan Wright    22             33         44         55
Peter Jones        66             77         88         99
James Bond     52              42         32         22
John Rambo     71              72         73         74
Spider Man       75             76         77        78
Iron Man         81              80         79        78

There is a header row for the table. The rest of the rows have data. In this table, there are 5 columns. The first cell of each column has a header for the column.

Coding with Perl
You can now have a Perl two-dimensional structure to hold the data for the spreadsheet. The most relevant is the hash of arrays. In this case, you have one hash, where each value of the hash is an array. The hash is a one-dimensional hash. The names of the students will be the keys of the hash. So, each key has an array. The marks for each student will be the values of the array, which is value for a key (name of student). The names of subjects will be the values of the first array. Remember, the value of the element of an array can be a number or a string. You end up with a 2D structure consisting of a 1D hash whose values of key/value pairs are 1D arrays.

Creating a Hash of Arrays
You can create the hash by declaration or by initialization.

Structure by Declaration
You create a Hash-of-Array structure by declaration by declaring a simple hash, e.g.

    my %Ha;

The next thing is to populate the structure.

Accessing a Hash Element
You access an element in a two dimensional hash-of-arrays with the following syntax:

    $hashName{'key'}[columnIndex]

Populating the Structure declared using One-by-One Insertion
In this section I explain how you can populate the hash of arrays structure, one element at a time. You can place elements into a hash-of-arrays structure, one-by-one. You do this using the above syntax. The following code places the first three rows of the above table into the structure, one element at a time:

use strict;

    my %Ha;

    $Ha{'Header'}[0] = "Geography";
    $Ha{'Header'}[1] = "History";
    $Ha{'Header'}[2] = "Physics";
    $Ha{'Header'}[3] = "Math";
    $Ha{'Joan Mary'}[0] = 50;
    $Ha{'Joan Mary'}[1] = 64;
    $Ha{'Joan Mary'}[2] = 14;
    $Ha{'Joan Mary'}[3] = 85;
    $Ha{'John Smith'}[0] = 78;
    $Ha{'John Smith'}[1] = 20;
    $Ha{'John Smith'}[2] = 85;
    $Ha{'John Smith'}[3] = 55;

The first three row elements have been inserted into the hash. Because of the syntax of inserting the elements, you end up with a hash-of-arrays. You can use this same syntax to change the element (key/value pair) values.

Reading Values from a Hash-of-Arrays One-by-One
The syntax to read a value from a two-dimensional hash-of-arrays into a variable is:

    $var = $hashName{'key'}[columnIndex];

So you read a value in a similar way that you place a value. The following code would place the first three rows of the above table into a hash-of-arrays and then print the row values out from the hash.

use strict;

    my %Ha;

    $Ha{'Header'}[0] = "Geography";
    $Ha{'Header'}[1] = "History";
    $Ha{'Header'}[2] = "Physics";
    $Ha{'Header'}[3] = "Math";
    $Ha{'Joan Mary'}[0] = 50;
    $Ha{'Joan Mary'}[1] = 64;
    $Ha{'Joan Mary'}[2] = 14;
    $Ha{'Joan Mary'}[3] = 85;
    $Ha{'John Smith'}[0] = 78;
    $Ha{'John Smith'}[1] = 20;
    $Ha{'John Smith'}[2] = 85;
    $Ha{'John Smith'}[3] = 55;

    my @arr = keys (%Ha);

    foreach my $i (0..2)
        {
            print $arr[$i], ": ";
            foreach my $j (0..3)
                {
                    print $Ha{$arr[$i]}[$j];
                    print  ", " if ($j != 3);
                }
            print "\n";
        }

Read and try the code. For my system, the output is:

John Smith: 78, 20, 85, 55
Joan Mary: 50, 64, 14, 85
Header: Geography, History, Physics, Math

This is not the order by keys that the hash was typed. In Perl, today, the order of the hash output is not necessarily the order typed. One solution to this is to print the header first and then print the names in alphabetical order of keys. The alphabetical order is not necessarily the order typed, but it makes sense. To achieve this, you would change the lower code of interest above to,

    my @arr = sort(keys (%Ha));

    print "Header: ", $Ha{'Header'}[0], ' ', $Ha{'Header'}[1], ' ', $Ha{'Header'}[2], ' ', $Ha{'Header'}[3], "\n";


    foreach my $i (0..2)
        {
            if ($arr[$i] ne 'Header')
                {
                    print $arr[$i], ": ";
                    foreach my $j (0..3)
                       {
                            print $Ha{$arr[$i]}[$j];
                            print  ", " if ($j != 3);
                       }
                    print "\n";
                }
        }

Placing Elements into a hash-of-Arrays Row-by-Row
You can place elements into a 2D hash-of-arrays one row at a time. The syntax to place a row into a hash-of-arrays is:

    $hashName{'key'} = [value1, value2, value3, …];

Note that the values of the row are in square brackets and not in arc or curly brackets. The following program places all the rows of the above table into a hash-of-arrays and then displays them (displays the data).

use strict;

    my %Ha;

    $Ha{'Header'} = ["Geography", "History", "Physics", "Math"];
    $Ha{'Joan Mary'} = [50, 64, 14, 85];
    $Ha{'John Smith'} = [78, 20, 85, 55];
    $Ha{'Suzan Wright'} = [22, 33, 44, 55];
    $Ha{'Peter Jones'} = [66, 77, 88, 99];
    $Ha{'James Bond'} = [52, 42, 32, 22];
    $Ha{'John Rambo'} = [71, 72, 73, 74];
    $Ha{'Spider Man'} = [75, 76, 77, 78];
    $Ha{'Iron Man'} = [81, 80, 79, 78];

    my @arr = sort(keys (%Ha));

    print "Header: ", $Ha{'Header'}[0], ' ', $Ha{'Header'}[1], ' ', $Ha{'Header'}[2], ' ', $Ha{'Header'}[3], "\n";

    foreach my $i (0..2)
        {
            if ($arr[$i] ne 'Header')
                {
                    print $arr[$i], ": ";
                    foreach my $j (0..3)
                       {
                            print $Ha{$arr[$i]}[$j];
                            print  ", " if ($j != 3);
                       }
                    print "\n";
                }
        }

Structure by Initialization
If you try to learn Perl from the specification or manual you would probably find the learning process difficult. Specifications or manuals are written for experts. A teacher like me has to read the manual and then present the knowledge in learnable form. That, I believe is what I have done for this Perl Advanced Course (link below), which I assume you are going through.

Back to 2D hash-of-arrays: “Hash-of-arrays by Initialization” is a phrase I have borrowed from C++. It means creating a hash-of-arrays structure where the left hand operand to the assignment operator is a variable and the right hand operand is the content (value) of the structure. The content is within special symbols.

With Perl, for the 2D initialization hash-of-arrays, you have the variable, this time with the scalar symbol, $ and not the hash symbol, %. Note, we are creating a hash-of-arrays by initialization and not by the normal way; so there is a difference. So you would have something like,

    my $hoaRef;

for the hash declaration, where hoaRef is the hash-of-arrays (hoa) name. $hoaRef is actually a reference (scalar variable that would hold a reference to a hash). The name is of your choice. Note that here, we are creating a hash-of-arrays by initialization and not a one-dimensional hash by initialization as in one of the previous parts of the series. So, the initialization approach here is different from the one in one of the previous parts of the series.

The right hand operand begins with { and ends with } immediately followed by “;”. Inside the curly brackets pair, you have rows. Each row is a one-dimensional array. Each 1D row is delimited by square brackets pair. The 1D rows are separated by commas (,) and not semicolons (;). Within each 1D array, the items are separated by commas. There is no comma after the last item in a 1D row and no comma after the last 1D row. Note: each array is preceded by a hash key and the => operator. So, the curly brackets for the whole hash, actually consist of key/value pairs where each value is a row. Read and try the following example that illustrates this:

use strict;

    my $hoaRef = {
                     'Header' => ["Geography", "History", "Physics", "Math"],
                     'Joan Mary' => [50, 64, 14, 85],
                     'John Smith' => [78, 20, 85, 55],
                     'Suzan Wright' => [22, 33, 44, 55],
                     'Peter Jones' => [66, 77, 88, 99],
                     'James Bond' => [52, 42, 32, 22],
                     'John Rambo' => [71, 72, 73, 74],
                     'Spider Man' => [75, 76, 77, 78],
                     'Iron Man' => [81, 80, 79, 78]
                 };

    print $$hoaRef{'John Smith'}[1];

To access an element, you type the variable name preceded by two consecutive $ symbols. You use the two different types of brackets as expected. Remember, here we are dealing with a hash-of-arrays by initialization and not a one-dimensional hash by initialization; so you have the double $. If it was a hash-of-arrays by declaration, you would have just one $.

Conclusion
To create a data structure of a hash of arrays you start with a hash that runs down in one dimension. Each row of the structure is an array that fits into an element of the hash. A row is actually the effective value of a key/value pair. The value of each key/value pair is a reference to a row.

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

NEXT

Comments

Become the Writer's Fan
Send the Writer a Message