Arrays
Perl supports arrays, which are ordered lists
of scalar values. In perl arrays can have any number of elements,
and grow automatically as needed! Array names all start with the
character @. Here are some possible array names:
@names, @ages, @html_tags.
Perl arrays are often called lists.
Array Literals (Constants)
You can create an array constant by enclosing a list of scalar values
inside parenthesis, with a comma between each adjacent scalars. For example, the following are all array constants:
(1,2,3)
("Dave Hollinger", "Joe Student", "Bill Clinton", "Homer Simpson")
("Amos Eaton", 200, "Lally", 130, "CII", 500)
An array literal can also include scalar variables as elements:
($name, $age, $weight)
This array constant depends on the values of the three scalar
variables referenced. You can use any perl expression that is a scalar
as an array element:
($a+$b, $c*$d, $f*100)
The above array has three elements. The empty array is simply
() and has zero elements.
List Constructor
Perl includes a notation called a list constructor that
provides a quick way to create an array (list) that holds a sequence of
integers. Here are a few examples:
(1..5) this is the same as (1, 2, 3, 4, 5)
(1.5..5.5) this is the same as (1.5, 2.5, 3.5, 4.5, 5.5)
(10..13,18,21) this is the same as (10, 11, 12, 13, 18, 21)
print and Array Literals
Many perl operators can take an array as an argument, for example the
print operator can handle an array constant like this:
print ("Name is ", $name, " age next year is ", $age+1, "\n" );
|
|
The argument given to print is an array literal that has 5 elements,
print sends each to stdout in order (with no spaces in between
elements). Although this looks like subroutine or function call
syntax (if you are used to 'C' or 'C++'), this is just giving the
print operator an array instead of a scalar!
Array Variables
Array variables can use the assignment operator just like scalars, so
you can do this:
@names = ("Bill", "William", "Billy", "Willy", "Billiam", "Billionaire" );
@jobs = ("CEO", "CFO", "UFO", "CIO", "CIA", "FBI");
@products = ("Apples", "Oranges", "Bananas", "Wireless Internet PDAs");
@prices = ( .25, .30, .40, $529.99);
@newprices = @prices;
print @names;
|
|
Fancy Stuff
You can do all kinds of fancy stuff with perl arrays, including the
following:
@a = (1,2,3);
@b = ("hello", @a, "bye"); # @b is ("hello",1,2,3,"bye")
@a = (@a,4); # @a is now (1, 2, 3, 4)
($x,$y,$z) = (1,2,3); # same as $x=1; $y=2; $z=3;
($f1, $f2) = @a; # now $f1 is 1 and $f2 is 2
|
|
Array Element Access
You can access individual elements of an array using the subscript
operator []. Since the result of accessing a single element of an
array is a scalar, when you use the subscript operator you also use a
$ in front of the array name instead of a @.
This seems confusing at first, but keep in mind that the result
of accessing an array element is a scalar. Just like in
C/C++, perl arrays start with a subscript of 0 - so the first element
in the array @names is $names[0] and
$names[1] is the second element in the array.
Here are some examples of array element access:
@vals = (10, 25, 50, 100, 200);
print ("The first value is ", $vals[0],"\n");
@class_names = ("Exploiting the Information World",
"Data Structures",
"Operating Systems",
"Artificial Intelligence",
"Programming Languages");
@class_sizes = (33,40,100,33,50);
print("The course ",$class_names[2]," has ",$class_sizes[2]," students\n");
$class_sizes[2] = $class_sizes[2] + 10;
print("The course ",$class_names[2]," has ",$class_sizes[2]," students\n");
|
|
Array Slices
You can operate on a subset of an array by using the slice operator.
Here are a few examples:
#define a student record for dave (the last three elements are grades)
@studentrec = ("Dave Hollinger", "hollingd@cs.rpi.edu", 123-45-6789,
34,88,22);
# now just get the grades:
@grades = @studentrec[3,4,5];
# This could also be done the hard way:
@grades = ($students[3], $students[4], $students[5]);
# You can make a slice that contains any of the array elements
# (and each any number of times).
@stuff = @grades[1,1,1,1,1,3..4];
print @stuff;
|
|
Notice that when using the slice operator, the result is always an
array - so you keep the leading "@". Here are some more examples:
@numbers = (1..10);
@evennumbers = (1..10)[1,3,5,7,9];
@oddnumbers = @numbers[0,2,4,6,8,10];
|
|
Array Size
Perl arrays grow automatically as you add elements to the end. If you
add an element past the end of a perl array - all the elements that
have not been defined get the special perl value undef.
You can get the index value of the last element in an array with the
special syntax $#arrayname (note it starts with
$ since it is a scalar value). You can get the size of an
array (the number of elements in the array) by evaluating
@arrayname in a scalar context, that is, in an
expression where perl is expecting a scalar value. Some examples:
# define an array
@nums = (1,2,3,5,8,13,21);
# find out the index of the last array element
$lastindex = $#nums;
# now find out how many array elements there are
$arraysize = @nums;
print("The array has $arraysize elements and the last one has index $lastindex\n");
|
|
Some Array Operators
Perl includes some array operators:
push - add an element to the end of an array
pop - take the last element out of an array
shift - take the first element out of an array
unshift - add an element at the beginning of an array
reverse - rearrange elements in an array in reverse order
sort - sort an array
chop - chops each element in an array
push and pop can be used to implement a
stack (Last-in-First-out) in which the top of the stack corresponds to the end of the array.
shift and
unshift also implement a stack, but now the front of the array is the top of the stack. You can implement a queue (First-in-First-Out)
using push and shift
:
#define an array
@letters = ("c", "l", "q", "t");
# this next line does the same thing as @letters = (@letters,"z");
push(@letters,"z");
# remove the last element
$lastelem = pop(@letters); #$lastelem is now "z"
# and @letters is ("c", "l", "q", "t")
# do it again
$lastelem = pop(@letters); # now $lastelem is "t"
# now @letters is ("c", "l", "q")
# add a new letter to the beginning of an array
unshift(@letters,"a"); # now @letters is ("a", "c", "l", "q")
# now take the first element off the array
$firstelem = shift(@letters); # $firstelem is "a"
# and @letters is now ("c", "l", "q")
# do it again
$firstelem = shift(@letters); # $firstelem is now "c"
# and @letters is now ("l", "q")
|
|
If you give pop or shift an empty array they
return the special perl value undef.
reverse does what you expect - it reverses the
order of elements in a perl array. However,
reverse doesn't change an array in place - it create a
new array! To reverse an array @a you have to do this:
@a = reverse(@a);.
sort orders the elements in an array in
string comparison order, that is - it uses the string
comparison operators to order the elements in an array. Just like
reverse, sort doesn't modify a named array -
it create a new array that contains the sorted elements. An
example:
@animals = ("zebra","lion","dog","grad student","albino squirrel","dolphin");
@ordered = sort( @animals );
# @ordered is ("albino squirrel","dog","dolphin","grad student","lion","zebra");
|
|
There are ways to change how perl sorts things (for example to sort numerically instead of as strings), but we need to cover subroutines first.
<STDIN> as an Array
You can assign <STDIN> to an array! This tells perl to
read all remaining lines from STDIN and put them in to an array. all remaining lines means until END-OF-FILE is found. An example:
# prompt for use input
print "Enter your name, age and favorite cookie on seperate lines\n";
# read everything from stdin
@lines = <STDIN>;
# chop off newlines using the array chop operator (chops each line)
chop(@lines);
print "Your name is $lines[0]\n";
print "Your age is $lines[1]\n";
print "Your cookie is $lines[2]\n";
|
|
another way to do this (perhaps better?)
# read in 3 lines an put in to variables, also chops each one
chop(($name,$age,$cookie) = <STDIN>);
# There might be more in STDIN - if so, we ignore it!
print "\n\n"; # force newline at end of input
print "Your name is $name\n";
print "Your age is $age\n";
print "Your cookie is $cookie\n";
|
|
Variable Interpolation of Arrays
Array variables can be interpolated inside double quoted strings. The
array name is replaced by a list of the elements with blanks between
each. An example:
@problem = ("the", "lack", "of", "parking");
print "The problem with RPI is @problem\n";
# Will output "The problem with RPI is the lack of parking" and newline.
|
|
Array elements can also be interpolated (we've already seen a few
examples). The index value can be an expression which is evaluated!
Some examples:
# create an array with numbers from 10 to 20
@numbers = (10..20);
# set up a scalar variable
$i = 3;
# print out some stuff showing array element variable interpolation
# will print "$numbers[3] is 13"
print "\$numbers[3] is $numbers[$i]\n";
#will print "$numbers[3+$i] is 16
print "\$numbers[3+\$i] is $numbers[$i+3]\n";
|
|
Perl Associative Arrays
Perl also supports associative arrays (sometimes called
hashes). An associative array is like an array in that it
contains a collection of scalar values that can be accessed by an
index. In perl arrays, the index is restricted to integer values
starting at 0 (and going up). In perl associative arrays the index can
be any scalar value - these indicies are often called keys.
The elements of an associative array have no order, they are just a
collection of (key,value) pairs that can be treated as a group. (An
associative array is like a set - no order is implied).
Associative Array Variables
Associative array variable names all start with the %
character. Although there are associative array operators in perl,
typically you deal with individual elements and not an entire
assoc. array. To access an individual element you use the {} index
operator (instead of the array [] operator), and when accessing the
scalar value of an assoc. array element you use a leading
$ (just like with array elements). Sounds confusing, so
perhaps some examples will help:
# create an element in the associative array %age that has the key
# "John Smith" and the value 45.
$age{"John Smith"} = 45;
# create another one
$age{"Mary Jones"} = 22;
print $age{"John Smith"}; # will print 45
|
|
As the above code shows, you can create an element of an associative
array simply by assigning a value to it. These associative arrays can
be as large as you want (as large as the memory in your computer).
Here is another example:
#define an assoc array that can lookup text name of each digit.
$text{0} = "zero";
$text{1} = "one";
$text{2} = "two";
$text{3} = "three";
$text{4} = "four";
$text{5} = "five";
$text{6} = "six";
$text{7} = "seven";
$text{8} = "eight";
$text{9} = "nine";
#define an assoc array that can lookup integer value digit name.
$val{"zero"} = 0;
$val{"one"} = 1;
$val{"two"} = 2;
$val{"three"} = 3;
$val{"four"} = 4;
$val{"five"} = 5;
$val{"six"} = 6;
$val{"seven"} = 7;
$val{"eight"} = 8;
$val{"nine"} = 9;
# try looking up a digit name given a number
print "Enter a number 0-9\n";
$num = <STDIN>;
chop($num);
print "The name is " . $text{$num} . "\n";
# try looking up a numeric value given a digit name
print "Enter the name of a number zero - nine\n";
$name = <STDIN>;
chop($name);
print "The value of $name is " . $val{$name} . "\n";
|
|
Associative Array Constants
You can create an entire associative array using an array constant, in
this case perl treats the first array element as a key and the next as
the corresponding value, then does the same with the remaining array
elements in order. For example, the following definition of an associative
array from an array constant:
%text = (0,"zero", 1, "one", 2, "two", 3, "three", 4, "four");
is shorthand for this:
$text{0} = "zero";
$text{1} = "one";
$text{2} = "two";
$text{3} = "three";
$text{4} = "four";
You can initialize an associative array from any array (including from
an array variable) in the same way. You can also create (or redefine)
an array variable from an associative array - in this case the
translation is reversed. The resulting array will be a list of the
keys and corresponding values. You have no control over the order of
key,value pairs that are put in the array (perl uses an internal
ordering for associative arrays that make the implementation
efficient). An example:
# create an associative array from an array constant.
%text = ("Bill",45,"Nancy",23,"John",23,"Mary",65);
# now copy this to an array variable
@somearray = %text;
# now print out this array and notice the order is different
# than the original constant array
print "Array is @somearry\n";
# The result I got was the following output:
# Array is Mary 65 Nancy 23 Bill 45 John 33
|
|
There is an alternate syntax for creating associative array literals using the => operator:
%text = (0 => "zero",
1 => "one",
2 => "two",
3 => "three",
4 => "four");
is shorthand for this:
$text{0} = "zero";
$text{1} = "one";
$text{2} = "two";
$text{3} = "three";
$text{4} = "four";
and this:
%text = (zero =>0,
one => 1,
two => 2,
"three" => 3,
"four" => 4);
is shorthand for this:
$val{"zero"} = 0;
$val{"one"} = 1;
$val{"two"} = 2;
$val{"three"} = 3;
$val{"four"} = 4;
Notice that when using the => operator the key value does not
need to be quoted (unless it contains whitespace).
No such key
If you attempt to access an element of an associative array using a key that
does not exist in the assoc. array - the result is the special perl
value undef.
Associative Array Operators
Perl supports some associative array operators including:
keys - returns a list (array) of the key values
values - returns a list (array) of the values
each - used to iterate over all the key/value pairs
delete - removed a key/value pair from an assoc. array
The keys operator extracts all the keys from
an associative array and creates an array holding all the scalar value keys.
The order of the keys in the resulting array is controlled by perl, so
you shouldn't make any assumptions about the order. The values operator gets an array made up of all the values in the associative array (just the values - none of the keys). An example:
# create an associative array
$price{"Boxer"} = 45000;
$price{"Beetle"} = 18000;
$price{"MonsterSUV"} = 40000;
$price{"MiniVan"} = 25000;
@carnames = keys(%price);
# @carnames now is something like (order could be different):
# ("Boxer", "Beetle", "MonsterSUV", "MiniVan")
@carprices = values(%price);
# @carprices now is something like (order could be different):
# (45000, 18000, 40000, 25000)
|
|
The delete operator deletes a single key/value pair from
an associative array. This is the only way to shrink an associative array.
An example:
# create an associative array
$price{"Boxer"} = 45000;
$price{"Beetle"} = 18000;
$price{"MonsterSUV"} = 40000;
$price{"MiniVan"} = 25000;
# now delete the record for Beetle (it's not worthy of inclusion!)
delete $price{"Beetle"};
@carnames = keys(%price);
# @carnames now is something like (order could be different):
# ("Boxer", "MonsterSUV", "MiniVan")
|
|
Variable Interpolation and Associative Arrays
There is no variable interpolation in doubly quoted strings for an
entire associative array (I'm not sure what to expect anyway), but you
can use individual elements of an associative array. For example:
$text{1} = "one";
$text{2} = "two";
$text{3} = "three";
$text{4} = "four";
$i = 2;
print "The name of $i is $text{$i}\n";
print "The name of 3 is $text{3}\n";
|
|
Exercises
1. Write some Perl code that will create an HTML table, where the
contents of the cells come from a Perl Array.
One possible solution: