## 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 = 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;
\$min = \$numbers;

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

```  perldoc -q array (plenty of good examples)