Recipe 4.3 Changing Array Size
4.3.1 Problem
You want to enlarge or truncate an
array. For example, you might truncate an array of employees that's
already sorted by salary to list the five highest-paid employees. Or,
if you know how big your array will get and that it will grow
piecemeal, it's more efficient to grab memory for it in one step by
enlarging just once than to keep pushing values
onto the end.
4.3.2 Solution
Assign to $#ARRAY
:
# grow or shrink @ARRAY
$#ARRAY = $NEW_LAST_ELEMENT_INDEX_NUMBER;
Assigning to an element past the end automatically extends the array:
$ARRAY[$NEW_LAST_ELEMENT_INDEX_NUMBER] = $VALUE;
4.3.3 Discussion
$#ARRAY is the
number of the last valid index in @ARRAY. If we
assign it a number smaller than its current value, we truncate the
array. Truncated elements are lost forever. If we assign
$#ARRAY a number larger than its current value,
the array grows. New elements have the undefined value.
$#ARRAY is not @ARRAY, though.
Although $#ARRAY is the last valid index in the
array, @ARRAY (in scalar context, as when treated
as a number) is the number of elements.
$#ARRAY is one less than @ARRAY
because array indices start at 0.
Here's some code that uses both. We have to say
scalar @array in the
print because Perl gives list context to (most)
functions' arguments, but we want @array in scalar
context.
sub what_about_that_array {
print "The array now has ", scalar(@people), " elements.\n";
print "The index of the last element is $#people.\n";
print "Element #3 is `$people[3]'.\n";
}
@people = qw(Crosby Stills Nash Young);
what_about_that_array( );
prints:
The array now has 4 elements.
The index of the last element is 3.
Element #3 is `Young'.
whereas:
$#people--;
what_about_that_array( );
prints:
The array now has 3 elements.
The index of the last element is 2.
Element #3 is `'.
Element #3 disappeared when we shortened the array. If we'd turned on
warnings (either with the -w
command-line option to Perl or with use warnings
inside the program), Perl would also have warned "use of
uninitialized value" because $people[3] is
undefined.
$#people = 10_000;
what_about_that_array( );
prints:
The array now has 10001 elements.
The index of the last element is 10000.
Element #3 is `'.
The "Young" element is now gone forever. Instead
of assigning to $#people, we could have said:
$people[10_000] = undef;
although this isn't exactly the same. If you have a three-element
array, as in:
@colors = qw(red blue green);
and you undef its last element:
undef $colors[2]; # green is gone
you still have a three-element array; its last element is just
undefined. If you pop the array, either via the
function or manually by changing $#colors:
$last_color = $colors[ $#colors-- ];
then the array grows shorter by one element.
Perl arrays are not sparse. In other words, if you have a
10,000th element, you must have the 9,999
other elements, too. They may be undefined, but they still take up
memory. For this reason, $array[time( )], or any
other construct that uses a very large integer as an array index, is
a really bad idea. Use a hash instead.
4.3.4 See Also
The discussion of the $#ARRAY notation in
perldata(1), also explained in the "List Values
and Arrays" section of Chapter 2 of Programming
Perl
|