Array Manipulation

Unlike the arrays in many popular programming languages, Perl arrays are not of fixed length. This makes it simple to expand or contract an array in Perl. Many array functions are provided in Perl to operate on arrays in various ways. The first group of functions allows you to dynamically change the size of an array.

Functions that Alter the Size of an Array

Perhaps the most important functions used by Perl programmers are those that allow Perl arrays to grow or shrink. This section demonstrates many of these Perl functions.

SPLIT

The split function takes a scalar variable and returns an array. The array is composed of the fields of the scalar delimited by whatever characters you specify. In its simplest case, split splits $_ on whitespace characters—blanks, tabs, and newlines. countwords.pl, shown next, uses split to count words in the standard input. See the folder CountWords.


% type countwords.pl
#
#   countwords.pl
#
while(<STDIN>)
{
    @words = split;       # split the line into 'words'
    $words += @words;     # add to the number of words
}
print "Total words = $words
";
%

The following line uses the array @words in a scalar context, which means that the number of elements in the array are added to $words.

$words += @words;

split can be used on any variable and with any delimiters. Regular expressions can be used as the criteria on which to split the scalar.

@fields = split("	", $line);     # split line on tabs
@fields = split(",", $line);      # split line on commas
@fields = split(/d+/, $line);    # split line on digits

Additionally, a nice use of split is to provide a third argument specifying the total number of fields that split will return.

@fields = split("	", $line, 2);

PUSH, UNSHIFT

The push function adds one or more elements to the end of an array.

@array = (5,10);               # array = 5, 10
push(@array, 20);              # array = 5, 10, 20
push(@array, 15,25);           # array = 5, 10, 20, 15, 25

The following example reads lines and creates an array consisting of those words that are numbers. A regular expression is used to determine if a word is a number. Only then is the number pushed onto the array. See the folder Numbers.


% type numbers.pl
#
#   numbers.pl
#
while(<STDIN>)
{
        @words = split;
        foreach $item (@words)
        {
                push(@numbers, $item) if $item =~ /^d+$/;
        }
}
print "@numbers
";
%

unshift is similar to push except that the elements are added to the beginning of the array rather than to the end of it.

POP, SHIFT

The pop function is used to remove the last element of an array. Here is an example that reads a line that presumably consists of a series of numerical values. The entire line is split into a series of numbers, then each number is popped off the array and processed. The processing here is simple: We just compute the square of the number. See the folder Pop.


% type pop.pl
#
#       pop.pl
#
print "enter some numbers ";
chomp($_ = <STDIN>);
@numbers = split;
while(@numbers)
{
        $x = pop(@numbers);
        print "$x	", $x * $x, "
";
}
%

The while test treats the array in a scalar content, returning its size. As each element of the array is popped, the size of the array changes. Eventually, the array will be empty.

shift is similar to pop except that the elements are removed from the beginning of the array rather than from the end of it.

SPLICE

splice can be used to insert elements into an array, displacing those where the insertion occurred. For example, the following invocation inserts the names Susan, Erin, and Patti, while removing Mike and Dave.

@emps = (Maria, Mike, Dave, Bob);
@removed = splice(@emps, 1, 2, Susan, Erin, Patti);

The first argument specifies the array to be affected. The next two arguments specify a starting position and a length. Remaining arguments are the values to be inserted. The starting position is zero based. If the length is zero, then the values are inserted.

Here is a program that generates some random numbers and inserts them into an array so that the array elements are always in order. This may not be the most efficient way to sort an array, but it does demonstrate how to insert using splice. See the folder Splice.


% type splice.pl
#
#   splice.pl
#
print "How many random numbers? ";
$items = <STDIN>;
for ($i = 0; $i < $items; $i++)
{
        $random = int( rand() * 100 );
        print "number is $random
";
        $found = 0;
        $amt = @vector;
        for ($k = 0; $k < $amt; $k++)
        {
                if ( $random < $vector[$k])
                {
                        splice(@vector,$k,0,$random);
                        $found = 1;
                        last;
                 }
        }
        push (@vector, $random) if ($found == 0);
}
print "Sorted array is: @vector
";
%

The rand function generates a random number between zero and almost one. To get these numbers into the range zero to almost 100, multiply by 100. To remove any fractional values, use the int function. Once the random number is generated, we need to see where it should be placed in the array so that the array is always ordered. The line

splice(@vector,$k,0,$random);

places the new random number in the array in its proper place. Here is a sample run of the program.

% perl splice.pl
How many random numbers? 4
number is 34
number is 77
number is 36
number is 83
Sorted array is: 34 36 77 83
%

Functions that Operate on Entire Arrays

The functions in this section receive arrays and manipulate them in some specified way.

REVERSE

The reverse function takes an array and returns a new array consisting of the original elements, but reversed.

@result  = reverse(@names);

The original array is unchanged. If you want to change it, you'll have to code, as shown next.

@names  = reverse(@names);

SORT

sort takes an array and returns a new array containing the original elements, but in dictionary-sorted order. The original array is unaltered.

@result  = sort(@names);

Here is a small program summarizing the reverse and the sort functions. See the folder RevSort.


% type revsort.pl
#
#       revsort.pl
#
@names = (Mike, Susan, Erin, Patti, Dave, Maria);
print "Original: @names
";
@reversed = reverse(@names);
print "Reversed: @reversed
";
@sorted = sort(@names);
print "Sorted:   @sorted
";
@revsort = reverse(sort(@names));
print "Rev Sort: @revsort
";
% perl revsort.pl
Original: Mike Susan Erin Patti Dave Maria
Reversed: Maria Dave Patti Erin Susan Mike
Sorted:   Dave Erin Maria Mike Patti Susan
Rev Sort: Susan Patti Mike Maria Erin Dave
%

Be careful if you wish to sort numbers. In order to do this, you need to know about subroutines, a topic that we visit in Chapter 5.

GREP

The grep function takes a criterion and a list, and returns an array of those elements in the list that match the criterion. The criteria can be a regular expression, a file operator, or even a subroutine. Later we see how to use a subroutine in this context. For now, we show a few examples using a regular expression and a file inquiry operator. See the folder Grep1.


% type grep1.pl
#
#   grep1.pl
#
#print "Enter some numbers ";
$line  = <STDIN>;
@elements = split(' ', $line);
@numbers = grep(/^d+$/, @elements);
print "The numbers are @numbers
";
% perl grep1.pl
Enter some numbers 10 20 hi there 30 40
The numbers are 10 20 30 40
%

In the above code, the line is split into fields and then grep is used to filter out the non-numbers. You can also give the grep function a file inquiry operator. See the folder Grep2.


% type grep2.pl
#
#       grep2.pl
#
print "Enter some names ";
$line  = <STDIN>;
@elements = split(' ', $line);
@files = grep(-f, @elements);
print "Files are @files
";
% perl grep2.pl
Enter some names . .. grep1.pl grep2.pl this that
Files are grep1.pl grep2.pl
%

In this case, the criterion is the file inquiry operator –f. The code represents an idiom to select file names from a group of names.

JOIN

The join function takes an array and a scalar, and produces a string consisting of each element in the array separated from one another by the scalar. Here is a popular idiom using this function. Suppose we have a list of names and we want to print them in sorted order. This is not a difficult problem, but suppose we try to be terse and hand the result of the sort to the print function.

@names = (mike, dave, tom);
print sort(@names);

The output for the above code segment is

davemiketom

The output is hard to read because there are no spaces between the array items. If you recall that putting quotes around the array causes a space between each of the output items, then you might be tempted to code as follows.

@names = (mike, dave, tom);
print "sort(@names)";

However, the output reveals that function names are not recognized within double quotes. Here is the output.

sort(mike dave tom)

This is where the join function comes to the rescue. You can code as follows and join will place whichever scalar you specify as the first argument as the separator between the array elements.

@names = (mike, dave, tom);
print join(" ", sort(@names)), "
";

Now the output is

dave mike tom

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.196.59