Tweet

Perl Arrays - a tutorial

Shlomi Fish

Introduction

(Editor's note: Also see our arrays howto entry for a simple introduction to the topic)

Arrays are a sequence of variables, whose members can be retrieved and assigned to by using their indices. An index passed to an array may well be, and usually is, another variable.

To refer to the $i'th element of the array @myarray, one uses the syntax $myarray[$i]. This element can be assigned to or its value can be retrieved, with the same notation.

Array indices are whole numbers and the first index is 0. As in the length of a string, the number of elements in an array is bounded only by the amount of available memory the computer has.

The following program prints the primes up to 200:

    #!/usr/bin/perl
    use strict;
    use warnings;
    my $num_primes = 0;
    my @primes;

    # Put 2 as the first prime so we won't have an empty array
    $primes[$num_primes] = 2;
    $num_primes++;

    MAIN_LOOP: 
    for my $number_to_check (3 .. 200)
    {
        for my $p (0 .. ($num_primes-1))
        {
            if ($number_to_check % $primes[$p] == 0)
            {
                next MAIN_LOOP;
            }
        }

        # If we reached this point it means $number_to_check is not
        # divisible by any prime number that came before it.
        $primes[$num_primes] = $number_to_check;
        $num_primes++;
    }

    for my $p (0 .. ($num_primes-1))
    {
        print $primes[$p], ", ";
    }
    print "\n";

The notation scalar(@myarray) can be used to refer to the number of elements in an array. This number is equal to the maximal index which was assigned in the array plus one. You will also see the notation $#myarray which is equal to the maximal index itself.

Thus, for example, the above program could have been written as follows:

    #!/usr/bin/perl
    use strict;
    use warnings;
    my @primes;
    $primes[0] = 2;

    MAIN_LOOP: 
    for my $number_to_check (3 .. 200)
    {
        for my $p (0 .. $#primes)
        {
            if ($number_to_check % $primes[$p] == 0)
            {
                next MAIN_LOOP;
            }
        }

        # If we reached this point it means $number_to_check is not
        # divisible by any prime number that came before it.
        $primes[scalar(@primes)] = $number_to_check;
    }

    for my $p (0 .. $#primes)
    {
        print $primes[$p], ", ";
    }
    print "\n";

The ',' operator

In Perl the comma (,) is an operator, which we often encounter in function calls. The comma concatenates two arrays. We can use it to initialize an array in one call:

    @lines = ("One fish", "two fish", "red fish", "blue fish");

    for $a (0 .. $#lines)
    {
        print $lines[$a], "\n";
    }

We can also use it to concatenate two existing arrays:

    @primes1 = (2,3,5);
    @primes2 = (7,11,13);
    @primes = (@primes1,@primes2,17);
    @primes = (@primes,19);

    for $a (0 .. $#primes)
    {
        print $primes[$a], "\n";
    }

So why it is used in function calls? In Perl every function accepts an array of arguments and returns an array of return values. That's why the comma is useful for calling functions which accept more than one argument.

Negative Indexes

The expression $myarray[-$n] is equivalent to $myarray[scalar(@myarray)-$n. I.e: subscripts with negative indexes return the $n'th element from the end of the array. So to get the value of the last element you can write $myarray[-1] and for the second last $myarray[-2], etc.

Note that one should also make sure that array subscripts that are continuously decremented will not underflow below 0, or else one will start getting the elements from the end of the array.

The foreach loop

By using the foreach loop we can iterate over all the elements of an array, and perform the same set of operations on each one of them. Here's an example:

    @numbers = (15,5,7,3,9,1,20,13,9,8,
        15,16,2,6,12,90);

    $max = $numbers[0];
    $min = $numbers[0];

    foreach $i (@numbers[1..$#numbers])
    {
        if ($i > $max)
        {
            $max = $i;
        }
        elsif ($i < $min)
        {
            $min = $i;
        }
    }

    print "The maximum is " . $max . "\n";
    print "The minimum is " . $min . "\n";

The foreach loop in the example assigns each of the elements of the array which was passed to it to $i in turn, and executes the same set of commands for each value.

The for keyword and the .. operator

The for keyword in Perl means exactly the same as foreach and you can use either one arbitrarily.

In list context, the Perl range operator, .. returns a list containing a sequence of consecutive integers. In the expression $a .. $b, for example, the range operator returns the sequence of consecutive integers from $a up to and including $b

Now one can fully understand the for $i (1 .. 10) construct that we used earlier.

Built-In Array Functions - push

The push function appends an element or an entire array to the end of an array variable. The syntax is push @array_to_append_to, @array_to_append or push @array, $elem1. For example, the primes program from earlier could be written as:

    #!/usr/bin/perl
    use strict;
    use warnings;
    my @primes;
    # Put 2 as the first prime so we won't have an empty array
    @primes = (2);

    MAIN_LOOP: 
    for my $number_to_check (3 .. 200)
    {
        foreach my $p (@primes)
        {
            if ($number_to_check % $p == 0)
            {
                next MAIN_LOOP;
            }
        }

        # If we reached this point it means $number_to_check is not
        # divisible by any prime number that came before it.
        push @primes, $number_to_check;
    }

    foreach my $p (@primes)
    {
        print $p, ", ";
    }
    print "\n";

Notice that push is equivalent to typing @array = (@array, $extra_elem), but push is recommended because it is less error-prone and it executes faster.

Built-In Array Functions - pop

pop extracts the last element from an array and returns it. Here's a short example to demonstrate it:

    #!/usr/bin/perl
    use strict;
    use warnings;
    # This program prints the numbers from 10 down to 1.
    my @numbers = (1 .. 10);
    while(scalar(@numbers) > 0)
    {
        my $i = pop(@numbers);
        print $i, "\n";
    }

Built-In Array Functions - shift

shift extracts the first element of an array and returns it. The array will be changed to contain only the elements that were previously with the 1 to scalar(@array)-1 indexes.

Here's the above example, while using shift instead of pop:

    #!/usr/bin/perl
    # This program prints the numbers 1 to 10.
    use strict;
    use warnings;
    my @numbers = (1 .. 10);
    while(scalar(@numbers) > 0)
    {
        my $i = shift(@numbers);
        print $i, "\n";
    }

Built-In Array Functions - join

The syntax is join($separator, @array) and what it does is concatenate the elements of @array while putting $separator in between. Here's an example:

    #!/usr/bin/perl
    use strict;
    use warnings;
    my @array = ("One fish", "Two fish", "Red Fish", "Blue Fish");

    print join("\n", @array), "\n";

which outputs:

    One fish
    Two fish
    Red Fish
    Blue Fish

Built-In Array Functions - reverse

The reverse function returns the array which contains the elements of the array passed to it as argument in reverse. Here's an example:

    #!/usr/bin/perl
    use strict;
    use warnings;
    print "Enter some lines:\n";

    my @mylines;
    my $line = <>;
    chomp($line);
    while ($line)
    {
        push @mylines, $line;
        $line = <>;
        chomp($line);
    }

    print "Your lines in reverse are:\n", join("\n", reverse(@mylines)), "\n";

Note that by typing scalar(reverse($scalar)) you get the string that contains the characters of $scalar in reverse. scalar(reverse(@array)) concatenates the array into one string and then reverses its characters.

The x operator

The expression (@array) x $num_times returns an array that is composed of $num_times copies of @array one after the other. The expression $scalar x $num_times, on the other hand, returns a string containing $num_times copies of $scalar concatenated together string-wise.

Wrapping the left operand in parenthesis, (or not doing so), is therefore important. It is usually a good idea to assign the left part to a variable before using x so you'll have the final expression ready.

Here's an example to illustrate the use:

    #!/usr/bin/perl
    use strict;
    use warnings;
    print "Test 1:\n";
    my @myarray = ("Hello", "World");
    my @array2 = ((@myarray) x 5);
    print join(", ", @array2), "\n\n";

    print "Test 2:\n";
    my @array3 = (@myarray x 5);
    print join(", ", @array3), "\n\n";

    print "Test 3:\n";
    my $string = "oncatc";
    print (($string x 6), "\n\n");

    print "Test 4:\n";
    print join("\n", (("hello") x 5)), "\n\n";

    print "Test 5:\n";
    print join("\n", ("hello" x 5)), "\n\n";

Can you guess what the output of this program will be?

Here's a spoiler

    Test 1:
    Hello, World, Hello, World, Hello, World, Hello, World, Hello, World

    Test 2:
    22222

    Test 3:
    oncatconcatconcatconcatconcatconcatc

    Test 4:
    hello
    hello
    hello
    hello
    hello

    Test 5:
    hellohellohellohellohello

See also

  perldoc -q array (plenty of good examples)
  perldoc perldata
  perldoc perllol
  perldoc perldsc
  perldoc -f push
  perldoc -f pop
  perldoc -f reverse
  perldoc -f join
  perldoc -f shift
[Top]