[Courses] [Perl] Part 11: More About Arrays

Dan dan at cellectivity.com
Sat Jun 11 01:00:47 EST 2005


LinuxChix Perl Course Part 11: More About Arrays

1) Introduction
2) Indexing Arrays
3) Flat Lists
4) Exercise
5) Answers to Previous Exercises
6) Acknowledgements
7) Licensing

          ----------------------------------------

1) Introduction

In the previous two weeks we've had a lot of fun with arrays. This
week is going to be a little "heavier", focusing on the details.

          ----------------------------------------

2) Indexing Arrays

As you might have guessed, arrays are indexed using good old "[]" -
but with a twist. The array name is (usually) preceded by a dollar
sign rather than an at-sign:

  my @list = ('some', 'words');
  print "$list[0]\n";       # Indexes start at zero.

As "man perldata" puts it: "$foo[1] is a part of @foo, not a part of
$foo. This may seem a bit weird, but that's okay, because it is
weird."

Don't let the humility of those words fool you: the system is
actually quite clever when you fully understand it. The "[]"
indicates that the variable is an array; the dollar sign indicates
that what you want from it is a scalar. It may seem obvious that you
would want a scalar, but Perl allows you to "slice" an array by
specifying multiple indices:

  my @chars = ('A', 'B', 'C', 'D', 'E', 'F');
  my @a = @chars[1,5];     # Gets B and F.
  my @b = @chars[1 .. 4];  # Gets B, C, D and E.
  my @c = @chars[1,3..5];  # Gets B, D, E and F.
  
  my @n = (2, 5);
  my @d = @chars[@n];      # Gets C and F.
  @chars[@n] = @n;         # Now @chars = A B 2 D E 5.

When you slice, you get back an array, so the variable name is
preceded by an "@".

A negative subscript is interpreted as though it had been added to
the length of the array, so negative numbers can be thought of as
"counting backwards from the end":

  my @chars = ('A', 'B', 'C', 'D', 'E', 'F');
  print "$chars[-2]\n";    # Prints "E".

It's not an error to access a non-existant subscript; you just get
back "undef" (the undefined value). If you assign to a non-existant
subscript, the array will be automatically extended.

          ----------------------------------------

3) Flat Lists

An array is a type of list. All lists in Perl are "flat": they can
only contain scalars, not other lists. Example:

  my @men = ('Bob', 'Joe');
  my @women = ('Alice', 'Ronda', 'Patricia');
  my @everyone = (@men, @women);     # Copy, not reference.
  my $length = $#everyone + 1;       # $length is 5.
  print "$length names: @everyone\n";

Trying to assign a whole array to a single array element won't work.
It would seem that you can't create an array of arrays, but Perl
provides a rather quirky way of getting around this limitation. We'll
see it when we get to references, but if you're really curious (and
bold), read "perldoc perllol". Note: in that document, brackets are
used not only for array indexing, but also for array references.

          ----------------------------------------

4) Exercise

a) It's often convenient to communicate with spreadsheets and
databases by writing files in Comma Separated Values (CSV) format.
Under Windows, if you double-click a file ending in ".CSV", it will
automatically be opened by Excel.

A CSV file might look like this:

  This is A1,This is B1,This is C1,
  This is A2,This is B2,This is C2,This is D2
  This row contains numbers,51,187,,

Suppose that this spreadsheet holds your old bank account records:

  Deposit,1000,1988-04-25,Payday
  Withdrawal,50,1988-04-28,
  Cheque,150,1988-04-30,Roof repair

You realise that it would make more sense for everything except
deposits to be negative, but the data are used in other calculations,
so you decide to insert a column with the changed data rather than
altering the original data.

Write a Perl program that inserts a new column between the amount and
the date (column C). The new column C should be exactly the same as
column B, except that it should be positive for deposits and negative
for everything else.

For extra credit, sort by date. (Don't do any complex date
conversions: the date is represented conveniently for this!)

          ----------------------------------------

5) Answers to Previous Exercises

a) The following program sorts its input:

  #!/usr/bin/perl -w
  use strict;
  
  my @input = <>;   # or use <STDIN> if you want.
  print sort(@input);

Note that we use "<>" instead of "<STDIN>". This is for convenience:
any file names provided on the command line will automatically be
opened and read.

b) The following program computes a sum:

  #!/usr/bin/perl -w
  use strict;
  
  my $line = <STDIN>;
  my @numbers = split( /\s*\+\s*/, $line );
  my $sum = 0;
  foreach my $n (@numbers) {
    $sum += $n;
  }
  print $sum;

The point of the example was to use "split". But it would make just
as much sense to use "m//g":

  my @numbers = ( $line =~ /(\d+)/g );

In fact, using "m//g" would have the advantage that we could more
easily extend the program to work with subtraction:

  #!/usr/bin/perl -w
  use strict;
  
  my $line = <STDIN>;
  my @numbers = ( $line =~ /(-|\+|\d+)/g );
  my $sum = 0;
  my $sign = '+';
  foreach my $x (@numbers) {
    if ( $x =~ /\d/ ) {
      if ( $sign eq '-' ) {
        $sum -= $x;
      }
      else {
        $sum += $x;
      }
    }
    else {
      $sign = $x;
    }
  }
  print $sum;

          ----------------------------------------

6) Acknowledgements

A big thank you to Jacinta Richardson for suggestions and
proofreading. More advanced Perl users might want to check out the
free material from Perl Training Australia
<http://www.perltraining.com.au/>, which she is a part of.

Other contributors include Meryll Larkin.

          ----------------------------------------

7) Licensing

This course (i.e., all parts of it) is copyright 2003-2005 by Dan
Richter and Alice Wood, and is released under the same license as
Perl itself (Artistic License or GPL, your choice). This is the
license of choice to make it easy for other people to integrate your
Perl code/documentation into their own projects. It is not generally
used in projects unrelated to Perl.



More information about the Courses mailing list