extra code in pp_concat, Take 2
[p5sagit/p5-mst-13.2.git] / pod / perllol.pod
CommitLineData
cb1a09d0 1=head1 NAME
4633a7c4 2
19799a22 3perllol - Manipulating Arrays of Arrays in Perl
4633a7c4 4
cb1a09d0 5=head1 DESCRIPTION
6
cea6626f 7=head2 Declaration and Access of Arrays of Arrays
4633a7c4 8
d808f88a 9The simplest thing to build is an array of arrays (sometimes imprecisely
19799a22 10called a list of lists). It's reasonably easy to understand, and
11almost everything that applies here will also be applicable later
12on with the fancier data structures.
4633a7c4 13
19799a22 14An array of an array is just a regular old array @AoA that you can
15get at with two subscripts, like C<$AoA[3][2]>. Here's a declaration
16of the array:
4633a7c4 17
19799a22 18 # assign to our array, an array of array references
19 @AoA = (
4633a7c4 20 [ "fred", "barney" ],
21 [ "george", "jane", "elroy" ],
22 [ "homer", "marge", "bart" ],
23 );
24
19799a22 25 print $AoA[2][2];
4633a7c4 26 bart
27
28Now you should be very careful that the outer bracket type
5a964f20 29is a round one, that is, a parenthesis. That's because you're assigning to
19799a22 30an @array, so you need parentheses. If you wanted there I<not> to be an @AoA,
4633a7c4 31but rather just a reference to it, you could do something more like this:
32
19799a22 33 # assign a reference to array of array references
34 $ref_to_AoA = [
4633a7c4 35 [ "fred", "barney", "pebbles", "bambam", "dino", ],
36 [ "homer", "bart", "marge", "maggie", ],
c2611fb3 37 [ "george", "jane", "elroy", "judy", ],
4633a7c4 38 ];
39
19799a22 40 print $ref_to_AoA->[2][2];
4633a7c4 41
54310121 42Notice that the outer bracket type has changed, and so our access syntax
4633a7c4 43has also changed. That's because unlike C, in perl you can't freely
19799a22 44interchange arrays and references thereto. $ref_to_AoA is a reference to an
45array, whereas @AoA is an array proper. Likewise, C<$AoA[2]> is not an
4633a7c4 46array, but an array ref. So how come you can write these:
47
19799a22 48 $AoA[2][2]
49 $ref_to_AoA->[2][2]
4633a7c4 50
51instead of having to write these:
52
19799a22 53 $AoA[2]->[2]
54 $ref_to_AoA->[2]->[2]
4633a7c4 55
56Well, that's because the rule is that on adjacent brackets only (whether
1fef88e7 57square or curly), you are free to omit the pointer dereferencing arrow.
4d9142af 58But you cannot do so for the very first one if it's a scalar containing
19799a22 59a reference, which means that $ref_to_AoA always needs it.
4633a7c4 60
cea6626f 61=head2 Growing Your Own
4633a7c4 62
63That's all well and good for declaration of a fixed data structure,
64but what if you wanted to add new elements on the fly, or build
65it up entirely from scratch?
66
67First, let's look at reading it in from a file. This is something like
68adding a row at a time. We'll assume that there's a flat file in which
69each line is a row and each word an element. If you're trying to develop an
19799a22 70@AoA array containing all these, here's the right way to do that:
4633a7c4 71
72 while (<>) {
73 @tmp = split;
19799a22 74 push @AoA, [ @tmp ];
54310121 75 }
4633a7c4 76
77You might also have loaded that from a function:
78
79 for $i ( 1 .. 10 ) {
19799a22 80 $AoA[$i] = [ somefunc($i) ];
4633a7c4 81 }
82
83Or you might have had a temporary variable sitting around with the
19799a22 84array in it.
4633a7c4 85
86 for $i ( 1 .. 10 ) {
87 @tmp = somefunc($i);
19799a22 88 $AoA[$i] = [ @tmp ];
4633a7c4 89 }
90
19799a22 91It's very important that you make sure to use the C<[]> array reference
4633a7c4 92constructor. That's because this will be very wrong:
93
19799a22 94 $AoA[$i] = @tmp;
4633a7c4 95
19799a22 96You see, assigning a named array like that to a scalar just counts the
54310121 97number of elements in @tmp, which probably isn't what you want.
4633a7c4 98
99If you are running under C<use strict>, you'll have to add some
100declarations to make it happy:
101
102 use strict;
19799a22 103 my(@AoA, @tmp);
4633a7c4 104 while (<>) {
105 @tmp = split;
19799a22 106 push @AoA, [ @tmp ];
54310121 107 }
4633a7c4 108
109Of course, you don't need the temporary array to have a name at all:
110
111 while (<>) {
19799a22 112 push @AoA, [ split ];
54310121 113 }
4633a7c4 114
115You also don't have to use push(). You could just make a direct assignment
116if you knew where you wanted to put it:
117
19799a22 118 my (@AoA, $i, $line);
1fef88e7 119 for $i ( 0 .. 10 ) {
4633a7c4 120 $line = <>;
19799a22 121 $AoA[$i] = [ split ' ', $line ];
54310121 122 }
4633a7c4 123
124or even just
125
19799a22 126 my (@AoA, $i);
1fef88e7 127 for $i ( 0 .. 10 ) {
19799a22 128 $AoA[$i] = [ split ' ', <> ];
54310121 129 }
4633a7c4 130
19799a22 131You should in general be leery of using functions that could
132potentially return lists in scalar context without explicitly stating
133such. This would be clearer to the casual reader:
4633a7c4 134
19799a22 135 my (@AoA, $i);
1fef88e7 136 for $i ( 0 .. 10 ) {
19799a22 137 $AoA[$i] = [ split ' ', scalar(<>) ];
54310121 138 }
4633a7c4 139
19799a22 140If you wanted to have a $ref_to_AoA variable as a reference to an array,
4633a7c4 141you'd have to do something like this:
142
143 while (<>) {
19799a22 144 push @$ref_to_AoA, [ split ];
54310121 145 }
4633a7c4 146
5a964f20 147Now you can add new rows. What about adding new columns? If you're
5f05dabc 148dealing with just matrices, it's often easiest to use simple assignment:
4633a7c4 149
150 for $x (1 .. 10) {
151 for $y (1 .. 10) {
19799a22 152 $AoA[$x][$y] = func($x, $y);
4633a7c4 153 }
154 }
155
156 for $x ( 3, 7, 9 ) {
19799a22 157 $AoA[$x][20] += func2($x);
54310121 158 }
4633a7c4 159
54310121 160It doesn't matter whether those elements are already
4633a7c4 161there or not: it'll gladly create them for you, setting
162intervening elements to C<undef> as need be.
163
5f05dabc 164If you wanted just to append to a row, you'd have
4633a7c4 165to do something a bit funnier looking:
166
167 # add new columns to an existing row
19799a22 168 push @{ $AoA[0] }, "wilma", "betty";
4633a7c4 169
5f05dabc 170Notice that I I<couldn't> say just:
4633a7c4 171
19799a22 172 push $AoA[0], "wilma", "betty"; # WRONG!
4633a7c4 173
174In fact, that wouldn't even compile. How come? Because the argument
175to push() must be a real array, not just a reference to such.
176
cea6626f 177=head2 Access and Printing
4633a7c4 178
54310121 179Now it's time to print your data structure out. How
5f05dabc 180are you going to do that? Well, if you want only one
4633a7c4 181of the elements, it's trivial:
182
19799a22 183 print $AoA[0][0];
4633a7c4 184
185If you want to print the whole thing, though, you can't
5f05dabc 186say
4633a7c4 187
19799a22 188 print @AoA; # WRONG
4633a7c4 189
5f05dabc 190because you'll get just references listed, and perl will never
54310121 191automatically dereference things for you. Instead, you have to
4633a7c4 192roll yourself a loop or two. This prints the whole structure,
193using the shell-style for() construct to loop across the outer
54310121 194set of subscripts.
4633a7c4 195
19799a22 196 for $aref ( @AoA ) {
4633a7c4 197 print "\t [ @$aref ],\n";
198 }
199
200If you wanted to keep track of subscripts, you might do this:
201
19799a22 202 for $i ( 0 .. $#AoA ) {
203 print "\t elt $i is [ @{$AoA[$i]} ],\n";
4633a7c4 204 }
205
206or maybe even this. Notice the inner loop.
207
19799a22 208 for $i ( 0 .. $#AoA ) {
209 for $j ( 0 .. $#{$AoA[$i]} ) {
210 print "elt $i $j is $AoA[$i][$j]\n";
4633a7c4 211 }
212 }
213
54310121 214As you can see, it's getting a bit complicated. That's why
4633a7c4 215sometimes is easier to take a temporary on your way through:
216
19799a22 217 for $i ( 0 .. $#AoA ) {
218 $aref = $AoA[$i];
4633a7c4 219 for $j ( 0 .. $#{$aref} ) {
19799a22 220 print "elt $i $j is $AoA[$i][$j]\n";
4633a7c4 221 }
222 }
223
5f05dabc 224Hmm... that's still a bit ugly. How about this:
4633a7c4 225
19799a22 226 for $i ( 0 .. $#AoA ) {
227 $aref = $AoA[$i];
4633a7c4 228 $n = @$aref - 1;
229 for $j ( 0 .. $n ) {
19799a22 230 print "elt $i $j is $AoA[$i][$j]\n";
4633a7c4 231 }
232 }
233
cea6626f 234=head2 Slices
4633a7c4 235
4d9142af 236If you want to get at a slice (part of a row) in a multidimensional
4633a7c4 237array, you're going to have to do some fancy subscripting. That's
238because while we have a nice synonym for single elements via the
239pointer arrow for dereferencing, no such convenience exists for slices.
240(Remember, of course, that you can always write a loop to do a slice
241operation.)
242
19799a22 243Here's how to do one operation using a loop. We'll assume an @AoA
4633a7c4 244variable as before.
245
246 @part = ();
54310121 247 $x = 4;
4633a7c4 248 for ($y = 7; $y < 13; $y++) {
19799a22 249 push @part, $AoA[$x][$y];
54310121 250 }
4633a7c4 251
252That same loop could be replaced with a slice operation:
253
19799a22 254 @part = @{ $AoA[4] } [ 7..12 ];
4633a7c4 255
256but as you might well imagine, this is pretty rough on the reader.
257
258Ah, but what if you wanted a I<two-dimensional slice>, such as having
5f05dabc 259$x run from 4..8 and $y run from 7 to 12? Hmm... here's the simple way:
4633a7c4 260
19799a22 261 @newAoA = ();
4633a7c4 262 for ($startx = $x = 4; $x <= 8; $x++) {
3e3baf6d 263 for ($starty = $y = 7; $y <= 12; $y++) {
19799a22 264 $newAoA[$x - $startx][$y - $starty] = $AoA[$x][$y];
4633a7c4 265 }
54310121 266 }
4633a7c4 267
54310121 268We can reduce some of the looping through slices
4633a7c4 269
270 for ($x = 4; $x <= 8; $x++) {
19799a22 271 push @newAoA, [ @{ $AoA[$x] } [ 7..12 ] ];
4633a7c4 272 }
273
274If you were into Schwartzian Transforms, you would probably
275have selected map for that
276
19799a22 277 @newAoA = map { [ @{ $AoA[$_] } [ 7..12 ] ] } 4 .. 8;
4633a7c4 278
279Although if your manager accused of seeking job security (or rapid
280insecurity) through inscrutable code, it would be hard to argue. :-)
281If I were you, I'd put that in a function:
282
19799a22 283 @newAoA = splice_2D( \@AoA, 4 => 8, 7 => 12 );
4633a7c4 284 sub splice_2D {
19799a22 285 my $lrr = shift; # ref to array of array refs!
54310121 286 my ($x_lo, $x_hi,
4633a7c4 287 $y_lo, $y_hi) = @_;
288
54310121 289 return map {
290 [ @{ $lrr->[$_] } [ $y_lo .. $y_hi ] ]
4633a7c4 291 } $x_lo .. $x_hi;
54310121 292 }
4633a7c4 293
294
4633a7c4 295=head1 SEE ALSO
296
297perldata(1), perlref(1), perldsc(1)
298
299=head1 AUTHOR
300
9607fc9c 301Tom Christiansen <F<tchrist@perl.com>>
4633a7c4 302
5a964f20 303Last update: Thu Jun 4 16:16:23 MDT 1998