Login

Perl: More on Lists and Hashes

Welcome to the first part of what should be the final two articles in our series on working with hashes and lists in Perl. This makes our eleventh article in the series and in it, we will wrap up the intermediate ways of working with hashes and lists. We’ll learn to add rows and columns to a two-dimensional list, replace them, create multi-dimensional lists, and write hashes and files to lists, then open and read from those same files over the next two articles.

Just as a refresher, in our previous article we went into detail about just what exactly a two-dimensional list was, how to print a single record from them and how to print an entire row. We also explained how to create variables, lists, and hashes using a two-dimensional array.

Setting Up the “Database”

I like to throw around that word two-dimensional. You’ll find it runs rampant throughout this article (and the last one). It’s a big word that soothes my little mind. So try not to get too annoyed as you see it thrown carelessly about.

For starters, let’s create a two-dimensional list for a book collection. Much to the chagrin of my girlfriend I have about nine billion books and nowhere to put them. So with this article I will try to appease her by adding some to a database. Here are the fields of data that will appear in our “database”:

Book Number

Author

Title

Genre

Number of Stars (how good the book was in a ranking of 1-5, with five being the best)

Which shelf on the bookshelf it is located

Here is the code to create the list and print it out to make sure everything is correct:

Here, in the above code, we created a fake set of headers to print out, which occupy row 0. When we print this code we get the following result:

# Author Title Genre Rating Location

1 Stephen King It Horror 5 Top

2 Clive Barker Imajica Horror 5 Top

3 Neil Gaiman American Gods Dark Fantasy 5 Top

4 Dean Koontz Tick-Tock Horror 1 GarbageCan

5 Charles Bukowski Letters from a Dirty Old Man Literature 5 Top

6 Chuck Pahluniak Fight Club Dark Fantasy 5 Middle

{mospagebreak title=How to Add Rows to a Two-Dimensional List}

Adding a row to a two-dimensional list is pretty simple. In this next example we are going to add a new book to our bookshelf using the push() function, which adds your new item to the end of the list (or the right-most side):

#!/usr/bin/perl

@Bookshelf = (

[" # ", " Author ", " Title ", " Genre "," Rating ", " Location "],

[' 1 ', ' Stephen King ', ' It ', ' Horror ', ' 5 ', ' Top '],

[' 2 ', ' Clive Barker ', ' Imajica ', ' Horror ', ' 5 ', ' Top '],

[' 3 ', ' Neil Gaiman ', ' American Gods ', ' Dark Fantasy', ' 5 ',

' Top '],

[' 4 ', ' Dean Koontz ', ' Tick-Tock ', ' Horror ', ' 1 ', '

GarbageCan '],

[' 5 ', ' Charles Bukowski ', ' Letters from a Dirty Old Man ', '

Literature ', ' 5 ', ' Top '],

[' 6 ', ' Chuck Pahluniak ', ' Fight Club ',' Dark Fantasy', ' 5 ',

' Middle ']

);

@NewBook = (‘ 7 ‘, ‘ T.H. White ‘, ‘ The Once and Future King ‘, ‘

Fantasy ‘, ‘ 5 ‘, ‘ Middle ‘);

push(@Bookshelf, [ @NewBook ]);

print "nn";

print @{@Bookshelf[7]};

Here we create our 2-D list called @Bookshelf and assign a bunch of values to it. We then create a normal list called @NewBook and assign values to it. Next we use the push() function to place the values in the @NewBook list into our 2-D list, which it appends to the end. Finally, we print the newly added row. The result is:

7 T.H. White The Once and Future King Fantasy 5 Middle

Another way to add a row to a two-dimensional list is like this:

#!/usr/bin/perl

@Bookshelf = (

[" # ", " Author ", " Title ", " Genre ", " Rating ", " Location "],

[' 1 ', ' Stephen King ', ' It ', ' Horror ', ' 5 ', ' Top '],

[' 2 ', ' Clive Barker ', ' Imajica ', ' Horror ', ' 5 ', ' Top '],

[' 3 ', ' Neil Gaiman ', ' American Gods ', ' Dark Fantasy ', ' 5 ',

' Top '],

[' 4 ', ' Dean Koontz ', ' Tick-Tock ', ' Horror ', ' 1 ', '

GarbageCan '],

[' 5 ', ' Charles Bukowski ', ' Letters from a Dirty Old Man ', '

Literature ', ' 5 ', ' Top '],

[' 6 ', ' Chuck Pahluniak ', ' Fight Club ', ' Dark Fantasy ', ' 5 ',

' Middle ']

);

@Bookshelf[7]= (

[' 7 ', ' T.H. White ', ' The Once and Future King ', ' Fantasy ', '

5 ', ' Middle ']

);

print @{@Bookshelf[7]};

This gives us the same result without using the push() function. Of course there is one other, shorter way to add a row:

Just as you can add a row to the end of a list, you can also add a column, though in truth it is a little more complex. In the sample below we are going to add a column to the end of each row. It will hold a value of “READ”, meaning of course that we have read the book. You may recall from an earlier article how to use the for loop. If not, don’t worry too much about it. Shortly we will be going more in-depth on loops (in another article or two in fact). Here is the awe-inspiring code:

#!/usr/bin/perl

@Bookshelf = (

[" # ", " Author ", " Title ", " Genre ", " Rating ", " Location "],

[' 1 ', ' Stephen King ', ' It ', ' Horror ', ' 5 ', ' Top '],

[' 2 ', ' Clive Barker ', ' Imajica ', ' Horror ', ' 5 ', ' Top '],

[' 3 ', ' Neil Gaiman ', ' American Gods ', ' Dark Fantasy ', ' 5 ',

' Top '],

[' 4 ', ' Dean Koontz ', ' Tick-Tock ', ' Horror ', ' 1 ', '

GarbageCan '],

[' 5 ', ' Charles Bukowski ', ' Letters from a Dirty Old Man ', '

Literature ', ' 5 ', ' Top '],

[' 6 ', ' Chuck Pahluniak ', ' Fight Club ', ' Dark Fantasy ', ' 5 ',

' Middle ']

);

$NumRows = @Bookshelf;

for($i = 0; $i < $NumRows; $i +=1)

{ $Bookshelf[$i][7] = "READ"}

print @{@Bookshelf[5]};

After creating our two-dimensional list and assigning values to it, we then create a variable called $NumRows and assign it the value of @Bookshelf. However, since a variable cannot contain a 2-D list, the number of rows is instead store in the variable. Which is exactly what we intended. Next we create a for loop that appends a new column with the value of “READ” to the end of each row. Finally, we print out the fifth row, just to ensure that it worked, giving us the result:

5 Charles Bukowski Letters from a Dirty Old Man Literature 5 Top READ

Of course we may not wish to automatically assign the same exact value to the end of each row, but the code for that is a little beyond the scope of this article.

If you are curious as to how the for loop works, here is a break down: the $i=0 part is the counter variable. $i < $NumRows is the criteria. Basically this says do this loop while $i is less than $NumRows. Finally, we have the incrementer, $i +=1. This adds one to the counter variable each time through the loop. The statement: { $Bookshelf[$i][7] = "READ"} adds a column to a different row each time through the loop (with the value “READ”). The loop breaks when the value in $i is greater than the value in $NumRows.

{mospagebreak title=Adding a Column to Individual Rows in a Two-Dimensional List}

Adding columns one row at a time is a lot simpler. Below we will add columns to two of of our rows, but not the rest:

#!/usr/bin/perl

@Bookshelf = (

[" # ", " Author ", " Title ", " Genre ", " Rating ", " Location "],

[' 1 ', ' Stephen King ', ' It ', ' Horror ', ' 5 ', ' Top '],

[' 2 ', ' Clive Barker ', ' Imajica ', ' Horror ', ' 5 ', ' Top '],

[' 3 ', ' Neil Gaiman ', ' American Gods ', ' Dark Fantasy ', ' 5 ',

' Top '],

[' 4 ', ' Dean Koontz ', ' Tick-Tock ', ' Horror ', ' 1 ', '

GarbageCan '],

[' 5 ', ' Charles Bukowski ', ' Letters from a Dirty Old Man ', '

Literature ', ' 5 ', ' Top '],

[' 6 ', ' Chuck Pahluniak ', ' Fight Club ', ' Dark Fantasy ', ' 5 ',

' Middle ']

);

$Bookshelf[1][7]=’READ';

$Bookshelf[2][7]=’UNREAD';

print @{@Bookshelf[1]};

print "nn";

print @{@Bookshelf[2]};

print "nn";

print @{@Bookshelf[3]};

Here we get the following output:

1 Stephen King It Horror 5 Top READ

2 Clive Barker Imajica Horror 5 Top UNREAD

3 Neil Gaiman American Gods Dark Fantasy 5 Top

Note that the last row we printed did not have the read/unread column, because we did not add it.

Well that’s it for this article. In our next article we will wrap up our discussion of lists and hashes (until a more advanced tutorial at any rate). Hope to see you there.