- Arrays & Lists
- Arrays of words are easily created
- Access arrays with numeric values
- The length of an array is its scalar value
- Arrays have no boundaries
- Arrays flatten out and do not nest
- Lists can have extra commas
- Use arrays like queues and stacks
- Extract sections of an array with array slices
- Assign chunks of an array with array slices
- Modify arrays in-place with splice
- Process arrays easily with map
- Select items out of an array with grep
Arrays & Lists
Arrays of words are easily created
The qw
operator makes creating arrays easy.It means "quote on whitespace into a list":
- # Perl 5
- my @stooges = qw( Larry Curly Moe Iggy );
- # or
- my @stooges = qw(
- Larry
- Curly
- Moe
- Iggy
- );
In Perl 6, the qw
is simplified:
- my @stooges = < Larry Curly Moe Iggy >;
- # or
- my @stooges = <
- Larry
- Curly
- Moe
- Iggy
- >;
The elements do not interpolate, so:
- my @array = qw( $100,000 ); # Perl 5
- my @array = < $100,000 >; # Perl 6
The single element of @array
is '$100,000'.
Access arrays with numeric values
To get a single scalar out of an array, access it with the []
and a $
sigil. All arrays in Perl start at 0.
- $stooges[1] # Curly
Arrays can also be accessed from the end by using negative offsets from the end.
- $stooges[-1] # Iggy
Reading a non-existent element gives undef
.
- $stooges[47] # undef
The length of an array is its scalar value
Put an array in scalar context to get its length. Some people like to explicitly use scalar
. Some don't.
- my $stooge_count = scalar @stooges; # 4
- my $stooge_count = @stooges; # 4
Don't take the length of an array with length
. That gives the length of a string.
- my $moe_length = length $stooges[@stooges/2];
- length $stooges[2];
- length 'Moe';
- 3;
Arrays have no boundaries
Arrays don't have any finite size, and don't have to be predeclared. Arrays change in size as necessary.
Arrays are also not sparse. This code makes a 10,000-element array.
- my @array = ();
- $array[10000] = 'x';
@array
is now 10,001 elements long (0-10,000), of which only one is populated. The other 10,000 are undef
.
Arrays flatten out and do not nest
Unlike PHP, arrays flatten into one big list when combined:
- my @sandwich = ( 'PB', 'J' );
- my @other_sandwich = ( 'B', 'L', 'T' );
- my @ingredients = ( @other_sandwich, @sandwich );
- # ( 'B', 'L', 'T', 'PB', 'J' )
This means you can't have an array "contain" another array, or a hash. To do that, you need references http://perl101.org/references.html.
Lists can have extra commas
One of the greatest features of Perl is the ability to have an extra comma at the end of a list. For example:
- my @array = (
- 'This thing',
- 'That thing',
- );
This makes adding or deleting items super easy when you edit your code, since you don't have to treat the last as a special case:
- my @array = (
- 'This thing',
- 'That thing',
- 'The other thing',
- );
Use arrays like queues and stacks
shift
removes from the beginning of the array:
- my $next_customer = shift @customers;
unshift
adds to the beginning of an array:
- unshift @customers, $line_jumper;
push
adds to the end of an array:
- push @customers, $dio; # The last in line
pop
removes from the end of an array:
- my $went_home = pop @customers;
Extract sections of an array with array slices
Array slices are just array accesses with multiple indices.
- my @a = 'a'..'z'; # 26 letters
- # a, e, i, o, u...
- my @vowels = @a[0,4,8,14,20];
- # And sometimes "y"
- push( @vowels, $a[-2] ) if rand > .5;
Note that when accessing an array slice, the sigil is @
, not $
, because you're returning an array, not a scalar. A common mistake for beginners is to access an array element with a @
sigil, not $
, and get back a slice, which is a list:
- # WRONG: Returns a 1-element list, or 1 in scalar context
- my $z = @a[-1];
- # RIGHT: Returns a single scalar element
- my $z = $a[-1];
Assign chunks of an array with array slices
You can have array slices as _lvalue_s, or values on the left side of the equals sign that can be assigned to.
- # Replace vowels with uppercase versions
- @a[0,4,8,14,20] = qw( A E I O U );
- # Swap first and last elements
- @a[0,-1] = @a[-1,0];
Note that the left and right slices must be of the same size. Any missing values on the right side of the equals sign will be replaced with undef.
Modify arrays in-place with splice
splice
lets you splice arrays into other arrays. Let's look at a few common ways of doing it wrong that should illustrate its usefulness:
- my @a = qw(Steve Stu Stan);
- $a[1] = ['Stewart', 'Zane'];
- # @a = ('Steve', ARRAY(0x841214c), 'Stan')
- # Memory address to an array reference
- my @a = qw(Steve Stu Stan);
- my @b = qw(Stewart Zane);
- $a[1] = @b;
- # @a = ('Steve', 2, 'Stan')
- # Returns a scalar reference, the length of @b
Now let's use splice
:
- @a = qw(Steve Stu Stan);
- splice @a, 1, 1, 'Stewart', 'Zane';
- # @a = ('Steve', 'Stewart', 'Zane', 'Stan')
- # This is just what we wanted
Let's break down the argument list for splice
: first, we name the array we're operating on (@a
); second, we define the offset (how far into the list we want the splice to start); third, we specify the length of the splice (how far forward from the offset we'll be deleting to make room for the new list); finally, we list the items we want inserted.
If all else fails, perldoc -f splice
.
Process arrays easily with map
map
is essentially a foreach
loop that returns a list.
You can use it to convert an array into a hash:
- my @array = ( 1, 2, 3, 4, 5 );
- my %hash = map { $_ => $_ * 9 } @array;
- # %hash = ( 1 => 9, 2 => 18, 3 => 27, 4 => 36, 5 => 45 )
or to transform a list:
- my @array = ( 'ReD', 'bLue', 'GrEEN' );
- my @fixed_array = map(ucfirst, map(lc, @array)); # note the nested 'map' functions
- # @fixed_array = ( 'Red', 'Blue', 'Green' )
Watch out, though: If you modify $_
, you will modify the source data. This means the above might be changed to:
- my @array = ( 'ReD', 'bLue', 'GrEEN' );
- map { $_ = ucfirst lc $_ } @array;
- # @array = ( 'Red', 'Blue', 'Green' )
Select items out of an array with grep
grep
is essentially a foreach loop that returns a list, but unlike map
, it will only return elements that cause the condition to return true.
- my @array = ( 0, 1, 2, 3, 4, 5 );
- my @new_array = grep { $_ * 9 } @array;
- # @new_array = ( 1, 2, 3, 4, 5 );
It will modify the source data the same way as map
, however:
- my @array = ( 0, 1, 2, 3, 4, 5 );
- my @new_array = grep { $_ *= 9 } @array;
- # @array = ( 0, 9, 18, 27, 36, 45 );
- # @new_array = ( 9, 18, 27, 36, 45 );
We can also pass regular expressions into grep
; in this example, we want only people with the surname 'Doe' put into our new array:
- my @people = (
- 'John Doe',
- 'Jane Doe',
- 'Joe Sixpack',
- 'John Q. Public',
- );
- my @does = grep { $_ =~ /\bDoe$/ } @people;
- # @does = ('John Doe', 'Jane Doe');
or even shorter
- my @does = grep { /\bDoe$/ } @people;
Want to contribute?
Submit a PR to github.com/petdance/perl101