A List of Lists
February 7, 2000
What if each item in a list was itself a list? Freaky,
and quite possible. Consider a list of car models for
one manufacturer ... for instance, "avalon",
"camry", and "celica". Now we might
have another list for another manufacturer, such as
"accord, civic, prelude". And we want to store
each of these lists as items of a list. Here is what the
initial list declaration might look like:
@carmodels=(["avalon","camry","celica"],
["accord","civic","prelude"],
["929","626","miata"]);
The list carmodels is declared like a normal list,
but each item is a list itself, contained within square
brackets. The syntax, especially which brackets are used
where (square, curly, or parentheses), becomes crucial in
manipulating lists and hashes. Because carmodels is
a list of lists, it is also sometimes known as a
two-dimensional array. To refer to a single scalar
item in carmodels you need to specify two dimensions:
$carmodels[1][2]
The above scalar would reference the value "prelude",
which is item index 2 of the list at index 1 of
carmodels. Now, suppose you want to append another
list of car models to carmodels ... this means adding
another list to the list. We can use the push function
to add a new item to the list, but note the syntax for
pushing a list as an item onto the list:
push(@carmodels,["sentra,stanza,altima"]);
The square brackets around the list to be pushed are crucial;
if you were to leave them off then "sentra",
"stanza", and "altima" would each be
added as individual scalar items to carmodels, rather
than as a single list item. Now, imagine that you want to
add a column to a list; that is, add a new item onto one of
the second-dimension lists, such as "tercel"
onto the list at index 0 (e.g. the Toyota list).
push (@{$carmodels[0]},"tercel");
Our syntax grows ever more obscure! Push requires a
destination list as its first paramter ... and we know that
the first item of carmodels is a list. The syntax for
communicating that is, as seen, @{$listname[index]}.
In other words, "the list at index within the
list listname". The end result will be that
"tercel" will be added onto the first list,
immediately after "celica". Similarly, we use the
@{$listname[index]} constructor to iterate over a
list-within-a-list. The following will traverse into each
list and output the car models contained within:
#iterate over list of lists
$index=0;
foreach $modellist (@carmodels) {
$index++;
print "List index $index:\n";
foreach $model (@{$modellist})
{print "\t$model\n"}
}
Now, if you've got that under your belt, you're probably
asking yourself, "Yeah but how can I double-sort this
list of lists?" What does that mean? Okay, it means
that we wish to sort carmodels by the first item in
each list, then we wish to output each second-dimension list
sorted with respect to itself. Doing so combines everything
we've seen above with list sorting from earlier. Hang on:
#double-sort list of lists
print "\nDouble-Sorted List of Lists:\n";
foreach $modellist
(sort {@{$a}[0] cmp @{$b}[0]} @carmodels)
{foreach $model (sort @{$modellist})
{print "$model "}
print"\n";}
Yields:
626 929 miata
accord civic prelude
avalon camry celica tercel
altima maxima sentra
You can see that the resulting list is sorted in both
dimensions, by rows and by columns. Time for an aspirin break.
All Sorts of Sorts: Hashes
The Perl You Need to Know
A List of Hashes
|