References and Data Structures

Creating and manipulating a hash of arrays

We will now create a slightly modified data structure, which will also hold the type of data in each line:

Boys Alex Bob Carl David Erik
Girls Anne Betty Carol Debby Edna
Countries Australia Belgium Canada Denmark England
Animals Alligator Bear Cat Dog Elephant

The natural way to hold this data structure is as a hash of arrays, or, better, as a reference to a hash of arrays. The hash keys are 'Boys', 'Girls', 'Countries', 'Animals', and the values are the references to the lists of names.

The naive way to build the data structure will be:


# 1. Create an array for each line (as before).

my @boys       = ('Alex',      'Bob',     'Carl',   'David',   'Erik'    );
my @girls      = ('Anne',      'Betty',   'Carol',  'Debby',   'Edna'    );
my @countries  = ('Australia', 'Belgium', 'Canada', 'Denmark', 'England' );
my @animals    = ('Alligator', 'Bear',    'Cat',    'Dog',     'Elephant');

# 2. Create a hash whose values will contain references
#    to the arrays of names.

%data_hash = ('Boys'       => \@boys,
              'Girls'      => \@girls,
              'Countries'  => \@countries,
              'Animals'    => \@animals    );

# 3. Create a reference to the entire data structure.

Alternatively, we can literally define the entire data structure as an anonymous structure, as the following:

$struct1 =
   { 'Boys'       => ['Alex',      'Bob',     'Carl',   'David',   'Erik'    ],
     'Girls'      => ['Anne',      'Betty',   'Carol',  'Debby',   'Edna'    ],
     'Countries'  => ['Australia', 'Belgium', 'Canada', 'Denmark', 'England' ],
     'Animals'    => ['Alligator', 'Bear',    'Cat',    'Dog',     'Elephant']

We will now try to read the data from a file (names1.txt).

Before doing that, let's practice two things:

Now we are ready to read data from file. We will read the types and their corresponding lists of names from the file, and add them to the structure using the same syntax we used to add the 'Fruits' list above. The only difference is that now we are doing it in a loop, and the type is stored in a variable ($type) which gets a new value every iteration.


open (SOURCE, "names1.txt") || die "cannot open file: $!";

while (<SOURCE>) {
   chomp ($_);
   ($type, $names) = split (/\s+/, $_);  #split line to two parts, delimited by a stretch of spaces
   @names = split (/:/, $names);            #get list of names, splitting by ':'
   $struct1->{$type} = [@names];            #add it to the data structure.

We showed above how to add another line to the structure. Let's now try to add another name, 'Iguana', to the Animals list:

push (@{$struct1->{'Animals'}}, 'Iguana');
Ugly syntax, indeed, but that's the best we can do.

Finally, let's print the entire structure in tab-delimited format, sorting the keys alphabetically:

foreach $type (sort keys %{$struct1}) {

   print "$type: \t";   #print type as the first word in the line, followed by ':'

   @names = @{$struct1->{$type}};  #get list of names for this type
   foreach $name (@names) {          #print names
      print "$name\t";
   print "\n";

Table of Contents.
Previous | Next.