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
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.
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.
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
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";
}
}
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 BasicsPerl 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