Home Accessibility Courses Diary The Mouth Facebook Resources Site Map About Us Contact
How to do multidimensional arrays (or rather lists and hashes) in Perl

In Perl, you can have a list of lists, a hash of hashes, a hash of lists or a list of hashes - in effect, two dimensional arrays but with much more flexibility.And where you can have two dimensional arrays, you can go further and have 3, 4, or more dimensions - you are limited only by your ingenuity.

With a list of lists, I could refer to the course number in a meal, and then within that course the option number - lists are ordered / keyed by a position starting at zero, so:
  $menuitem[1][2]
would refer to the second course (the first course being number 0) and the third option for that course.

With a hash of hashes, I could refer to a member of staff by name, and then their normal working hours for a day of the week by the name of the day - so
  $shifthours{Anna}{Tuesday}

Note - curly braces for a hash (an unordered collection keyed by name) and square brackets for a list (an ordered / sortable collection, keyed by number). And I can add more dimensions to my structure, and choose which are lists and which are hashes.




With "autovivification", you don't even need to declare your variables / lists / hashes ahead of time - Perl will automatically create them and the containers needed for them too when you first refer to them (implying the existence of a list, for example, by making reference to a member of the list). All very clever, but you can also work at a higher level by referring to a list or a hash as a whole, and where you've got (for example) a hash of hashes, you can refer to the whole structure, to a hash within the outer hash, or to an individual scalar member simply by how you write your code. And this means that - with a bit of practice - you can write short code to handle these complex structures really efficiently.

On the private intermediate / advanced Perl course that I was presenting yesterday, I was asked to demonstrate the setup and use of a hash of hashes, and I took as my example the data from a log file of all the visits to our web site on a day last November. The "outer" hash - the first set of curly braces - is used in this example to hold the remote computer's name or IP address, and within that (and within each record), I've noted down the most recent visit from that IP, with a hash containing attribute names and values. So I can reference:
  $final{"crawl-66-249-72-193.googlebot.com"}{"url"}
to look up the URL that's held for the Google crawler at 66.249.72.173, for example.

Here - and it's surprisingly short - is the code I used to set up that hash of hashes:

  @fnames = qw(host s1 s2 date offset method url level status size);
  while (<FH>) {
    @flds = split;
    my %record;
    for ($k=0; $k<@fnames; $k++) {
      $record{$fnames[$k]} = $flds[$k]; }
    $final{$flds[0]} = \%record;
  }


The quoted list of words (qw) that's initialised at the beginning is used to assign the names / keys to the fields on each record, and then the code loops though all lines of the file which I have already opened on the file handle FH.

Each line is split into a list of fields, which are then transferred into a hash using the list of names already supplied before the loop. And the address of this (single dimensioned) hash is then stored into the outer hash, turning it into the second dimension or inner hash.

Finally, note the use of my which means that the name %record is a temporary one which is released at the end of each time through the loop, so that when the loop runs for the next line read from the file, %record will be at another / different memory address.

The code might be short - but it does a lot! The complete program is [here], and there's an extended version (a hash of lists of hashes!) [here]. That latter example turns out to be even shorter and I have used by three dimensions as follows:
1. The visiting IP (a hash)
2. A list of hits from that IP (a list)
3. The property of the visit [url, return code, time, etc] (a hash)

If you're looking for a short example showing lists of lists, we have one [here] and there's another that sets up the structure scalar by scalar [here]. And there's a simple setup of a hash of lists [here].

Please don't expect to feel comfortable with this Perl on the first day you look at the language - the code might be short, it's actually quite easy to write once you're familiar with the techniques and have had some practice, but there are quite a few techniques to learn even in these few lines. For newcomers to Perl, we offer a Perl Programming Course on which we briefly cover multidimensional structures on the last day. For more advanced users, we offer an intermediate course - Perl for Larger Projects which covers the subject in more depth, together with topics such as Object Oriented Perl which uses many of the same techniques and technology shown in this example.

(written 2012-01-14, updated 2012-01-28)

 
Associated topics are indexed as below, or enter http://melksh.am/nnnn for individual articles
P217 - Perl - More than Simple Lists and Hashes!
  [3906] Taking the lead, not the dog, for a walk. - (2012-10-28)
  [3444] Take the dog on a lead - do not carry her. Perl references. - (2011-09-17)
  [3406] Not multidimentional arrays - but lists of lists. Much more flexible. Perl! - (2011-08-26)
  [3399] From fish, loaves and apples to money, plastic cards and BACS (Perl references explained) - (2011-08-20)
  [3118] Arrays of arrays - or 2D arrays. How to program tables. - (2011-01-02)
  [3105] Adventure with references to lists and lists of references - (2010-12-26)
  [3072] Finding elements common to many lists / arrays - (2010-11-26)
  [3007] Setting up a matrix of data (2D array) for processing in your program - (2010-10-21)
  [2996] Copying - duplicating data, or just adding a name? Perl and Python compared - (2010-10-12)
  [2877] Further more advanced Perl examples - (2010-07-19)
  [2840] Just pass a pointer - do not duplicate the data - (2010-06-30)
  [2241] Perl references - $$var and \$var notations - (2009-06-15)
  [1514] Autovivification - the magic appearance of variables in Perl - (2008-01-21)
  [293] Course follow-ups - (2005-04-27)
  [43] Hash of lists in Perl - (2004-09-09)


Back to
Tcl - apparently odd behaviour of string trimleft
Previous and next
or
Horse's mouth home
Forward to
A busy start to 2012
Some other Articles
Perl - calls to methods that use => - what do they mean?
Melksham Area - buses, trains, cycles, and roads. Meeting, 17.1.2012
Transport in Cambridgeshire - seen by an outside observer. What can Wiltshire learn?
A busy start to 2012
How to do multidimensional arrays (or rather lists and hashes) in Perl
Tcl - apparently odd behaviour of string trimleft
Multiple buttons calling the same proc in wish (tcl/tk)
Perl functions such as chop change their input parameters
New in Java 7 - and why we are not running public Java 7 courses
Adding Expect on top of Tcl - what is it and where can I get a training course to learn about it?
4255 posts, page by page
Link to page ... 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86 at 50 posts per page


This is a page archived from The Horse's Mouth at http://www.wellho.net/horse/ - the diary and writings of Graham Ellis. Every attempt was made to provide current information at the time the page was written, but things do move forward in our business - new software releases, price changes, new techniques. Please check back via our main site for current courses, prices, versions, etc - any mention of a price in "The Horse's Mouth" cannot be taken as an offer to supply at that price.

Link to Ezine home page (for reading).
Link to Blogging home page (to add comments).

You can Add a comment or ranking to this page

© WELL HOUSE CONSULTANTS LTD., 2014: Well House Manor • 48 Spa Road • Melksham, Wiltshire • United Kingdom • SN12 7NY
PH: 01144 1225 708225 • FAX: 01144 1225 899360 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho

PAGE: http://www.wellho.net/mouth/3577_How ... -Perl.html • PAGE BUILT: Sun Mar 30 15:20:58 2014 • BUILD SYSTEM: WomanWithCat