Home » Tutorials » Arrays |

Shlomi Fish

(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";

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.

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.

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 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.

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.

`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"; }

`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"; }

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

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 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

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