1 |
argrath |
1.1 |
|
2 |
|
|
=encoding euc-jp |
3 |
|
|
|
4 |
|
|
=head1 NAME |
5 |
|
|
|
6 |
|
|
=begin original |
7 |
|
|
|
8 |
|
|
perllol - Manipulating Arrays of Arrays in Perl |
9 |
|
|
|
10 |
|
|
=end original |
11 |
|
|
|
12 |
|
|
perllol - Perl で配列の配列を操作する |
13 |
|
|
|
14 |
|
|
=head1 DESCRIPTION |
15 |
|
|
|
16 |
|
|
=head2 Declaration and Access of Arrays of Arrays |
17 |
|
|
|
18 |
|
|
(配列の配列の定義とアクセス) |
19 |
|
|
|
20 |
|
|
=begin original |
21 |
|
|
|
22 |
|
|
The simplest two-level data structure to build in Perl is an array of |
23 |
|
|
arrays, sometimes casually called a list of lists. It's reasonably easy to |
24 |
|
|
understand, and almost everything that applies here will also be applicable |
25 |
|
|
later on with the fancier data structures. |
26 |
|
|
|
27 |
|
|
=end original |
28 |
|
|
|
29 |
|
|
Perl で構築する一番簡単なデータ構造は、配列の配列(カジュアルに |
30 |
|
|
リストのリストとも呼ばれることがあります)です。 |
31 |
|
|
これは理解しやすく、そしてより複雑なデータ構造に対しても |
32 |
|
|
適用することのできるものです。 |
33 |
|
|
|
34 |
|
|
=begin original |
35 |
|
|
|
36 |
|
|
An array of an array is just a regular old array @AoA that you can |
37 |
|
|
get at with two subscripts, like C<$AoA[3][2]>. Here's a declaration |
38 |
|
|
of the array: |
39 |
|
|
|
40 |
|
|
=end original |
41 |
|
|
|
42 |
|
|
配列の配列は、通常の古い配列 @AoA のようなものです; これは |
43 |
|
|
C<$AoA[3][2]> のように、二つの添え字で要素を取得することができます。 |
44 |
|
|
配列の宣言の例を挙げましょう。 |
45 |
|
|
|
46 |
|
|
use 5.010; # so we can use say() |
47 |
|
|
|
48 |
|
|
=begin original |
49 |
|
|
|
50 |
|
|
# assign to our array, an array of array references |
51 |
|
|
@AoA = ( |
52 |
|
|
[ "fred", "barney", "pebbles", "bambam", "dino", ], |
53 |
|
|
[ "george", "jane", "elroy", "judy", ], |
54 |
|
|
[ "homer", "bart", "marge", "maggie", ], |
55 |
|
|
); |
56 |
|
|
say $AoA[2][1]; |
57 |
|
|
bart |
58 |
|
|
|
59 |
|
|
=end original |
60 |
|
|
|
61 |
|
|
# 配列に配列へのリファレンスの配列を代入する |
62 |
|
|
@AoA = ( |
63 |
|
|
[ "fred", "barney", "pebbles", "bambam", "dino", ], |
64 |
|
|
[ "george", "jane", "elroy", "judy", ], |
65 |
|
|
[ "homer", "bart", "marge", "maggie", ], |
66 |
|
|
); |
67 |
|
|
say $AoA[2][1]; |
68 |
|
|
bart |
69 |
|
|
|
70 |
|
|
=begin original |
71 |
|
|
|
72 |
|
|
Now you should be very careful that the outer bracket type |
73 |
|
|
is a round one, that is, a parenthesis. That's because you're assigning to |
74 |
|
|
an @array, so you need parentheses. If you wanted there I<not> to be an @AoA, |
75 |
|
|
but rather just a reference to it, you could do something more like this: |
76 |
|
|
|
77 |
|
|
=end original |
78 |
|
|
|
79 |
|
|
このとき、外側の括弧が丸括弧であったことに注意すべきです。 |
80 |
|
|
これは、上の例では@配列に代入するので丸括弧を使う必要があったためなのです。 |
81 |
|
|
もし @AoA ではなくて、単にリファレンスを代入したかったというのであれば、 |
82 |
|
|
次のように書くことができます: |
83 |
|
|
|
84 |
|
|
=begin original |
85 |
|
|
|
86 |
|
|
# assign a reference to array of array references |
87 |
|
|
$ref_to_AoA = [ |
88 |
|
|
[ "fred", "barney", "pebbles", "bambam", "dino", ], |
89 |
|
|
[ "george", "jane", "elroy", "judy", ], |
90 |
|
|
[ "homer", "bart", "marge", "maggie", ], |
91 |
|
|
]; |
92 |
|
|
say $ref_to_AoA->[2][1]; |
93 |
|
|
bart |
94 |
|
|
|
95 |
|
|
=end original |
96 |
|
|
|
97 |
|
|
# 配列へのリファレンスの配列へのリファレンスを代入する |
98 |
|
|
$ref_to_AoA = [ |
99 |
|
|
[ "fred", "barney", "pebbles", "bambam", "dino", ], |
100 |
|
|
[ "george", "jane", "elroy", "judy", ], |
101 |
|
|
[ "homer", "bart", "marge", "maggie", ], |
102 |
|
|
]; |
103 |
|
|
say $ref_to_AoA->[2][1]; |
104 |
|
|
bart |
105 |
|
|
|
106 |
|
|
=begin original |
107 |
|
|
|
108 |
|
|
Notice that the outer bracket type has changed, and so our access syntax |
109 |
|
|
has also changed. That's because unlike C, in perl you can't freely |
110 |
|
|
interchange arrays and references thereto. $ref_to_AoA is a reference to an |
111 |
|
|
array, whereas @AoA is an array proper. Likewise, C<$AoA[2]> is not an |
112 |
|
|
array, but an array ref. So how come you can write these: |
113 |
|
|
|
114 |
|
|
=end original |
115 |
|
|
|
116 |
|
|
外側の括弧が変わったことと、アクセスの構文が変わっているということに |
117 |
|
|
注目してください。 |
118 |
|
|
これは C とは違って、Perl では配列と参照とを自由に交換できないからです。 |
119 |
|
|
$ref_to_AoA は配列への参照です; その配列は @AoA で、これがまた配列です。 |
120 |
|
|
同様に、C<$AoA[2]> は配列ではなく配列への参照です。 |
121 |
|
|
ですから: |
122 |
|
|
|
123 |
|
|
$AoA[2][2] |
124 |
|
|
$ref_to_AoA->[2][2] |
125 |
|
|
|
126 |
|
|
=begin original |
127 |
|
|
|
128 |
|
|
instead of having to write these: |
129 |
|
|
|
130 |
|
|
=end original |
131 |
|
|
|
132 |
|
|
これは、以下のような書き方でも同じことになります: |
133 |
|
|
|
134 |
|
|
$AoA[2]->[2] |
135 |
|
|
$ref_to_AoA->[2]->[2] |
136 |
|
|
|
137 |
|
|
=begin original |
138 |
|
|
|
139 |
|
|
Well, that's because the rule is that on adjacent brackets only (whether |
140 |
|
|
square or curly), you are free to omit the pointer dereferencing arrow. |
141 |
|
|
But you cannot do so for the very first one if it's a scalar containing |
142 |
|
|
a reference, which means that $ref_to_AoA always needs it. |
143 |
|
|
|
144 |
|
|
=end original |
145 |
|
|
|
146 |
|
|
この規則は隣り合ったかっこ(それが大かっこだろうが中かっこだろうが) |
147 |
|
|
だけのものなので、参照外しをする矢印を自由に省略できます。 |
148 |
|
|
けれども一番最初にある矢印だけは、それがリファレンスを保持する |
149 |
|
|
スカラであるために省略することはできません; これは $ref_to_AoA が常に |
150 |
|
|
必要とするものです。 |
151 |
|
|
|
152 |
|
|
=head2 Growing Your Own |
153 |
|
|
|
154 |
|
|
(大きくする) |
155 |
|
|
|
156 |
|
|
=begin original |
157 |
|
|
|
158 |
|
|
That's all well and good for declaration of a fixed data structure, |
159 |
|
|
but what if you wanted to add new elements on the fly, or build |
160 |
|
|
it up entirely from scratch? |
161 |
|
|
|
162 |
|
|
=end original |
163 |
|
|
|
164 |
|
|
固定的なデータ構造の宣言は良いのですが、その場で新しい要素を |
165 |
|
|
追加したいとき、あるいは完全に 0 から作り上げたいときにはどうするのでしょう? |
166 |
|
|
|
167 |
|
|
=begin original |
168 |
|
|
|
169 |
|
|
First, let's look at reading it in from a file. This is something like |
170 |
|
|
adding a row at a time. We'll assume that there's a flat file in which |
171 |
|
|
each line is a row and each word an element. If you're trying to develop an |
172 |
|
|
@AoA array containing all these, here's the right way to do that: |
173 |
|
|
|
174 |
|
|
=end original |
175 |
|
|
|
176 |
|
|
まず最初に、ファイルから読み込むことを見てみましょう。 |
177 |
|
|
これは一度に一つの行を追加していくようなものです。 |
178 |
|
|
私たちはここで、読み込んでいるファイルが、一行(line)が一つの行(row)に |
179 |
|
|
対応し、各単語が要素に対応しているようなフラットなファイルであると |
180 |
|
|
仮定しています。 |
181 |
|
|
もし配列 @AoA にそういった物を設定しようとするのであれば、 |
182 |
|
|
それは以下のようなやり方になります: |
183 |
|
|
|
184 |
|
|
while (<>) { |
185 |
|
|
@tmp = split; |
186 |
|
|
push @AoA, [ @tmp ]; |
187 |
|
|
} |
188 |
|
|
|
189 |
|
|
=begin original |
190 |
|
|
|
191 |
|
|
You might also have loaded that from a function: |
192 |
|
|
|
193 |
|
|
=end original |
194 |
|
|
|
195 |
|
|
関数を使って読み込むこともできます: |
196 |
|
|
|
197 |
|
|
for $i ( 1 .. 10 ) { |
198 |
|
|
$AoA[$i] = [ somefunc($i) ]; |
199 |
|
|
} |
200 |
|
|
|
201 |
|
|
=begin original |
202 |
|
|
|
203 |
|
|
Or you might have had a temporary variable sitting around with the |
204 |
|
|
array in it. |
205 |
|
|
|
206 |
|
|
=end original |
207 |
|
|
|
208 |
|
|
あるいは、配列に設定するために使う一時変数を使うこともできます。 |
209 |
|
|
|
210 |
|
|
for $i ( 1 .. 10 ) { |
211 |
|
|
@tmp = somefunc($i); |
212 |
|
|
$AoA[$i] = [ @tmp ]; |
213 |
|
|
} |
214 |
|
|
|
215 |
|
|
=begin original |
216 |
|
|
|
217 |
|
|
It's important you make sure to use the C<[ ]> array reference |
218 |
|
|
constructor. That's because this wouldn't work: |
219 |
|
|
|
220 |
|
|
=end original |
221 |
|
|
|
222 |
|
|
配列への参照のコンストラクタである C<[ ]> を使うことが重要です。 |
223 |
|
|
次のように書いてしまうのはとてもまずいやりかたです: |
224 |
|
|
|
225 |
|
|
$AoA[$i] = @tmp; # WRONG! |
226 |
|
|
|
227 |
|
|
=begin original |
228 |
|
|
|
229 |
|
|
The reason that doesn't do what you want is because assigning a |
230 |
|
|
named array like that to a scalar is taking an array in scalar |
231 |
|
|
context, which means just counts the number of elements in @tmp. |
232 |
|
|
|
233 |
|
|
=end original |
234 |
|
|
|
235 |
|
|
あなたが望んでいることをしない理由は、スカラに対するような名前付き配列の |
236 |
|
|
代入は、配列をスカラコンテキストとして扱い、これは単に @tmp の要素の数を |
237 |
|
|
数えることになるからです。 |
238 |
|
|
|
239 |
|
|
=begin original |
240 |
|
|
|
241 |
|
|
If you are running under C<use strict> (and if you aren't, why in |
242 |
|
|
the world aren't you?), you'll have to add some declarations to |
243 |
|
|
make it happy: |
244 |
|
|
|
245 |
|
|
=end original |
246 |
|
|
|
247 |
|
|
C<use strict> の元で実行するのであれば、(そしてもししていないのなら、 |
248 |
|
|
どうしてしていないの?) 以下の様にちょっと宣言を付け加えるとよいでしょう: |
249 |
|
|
|
250 |
|
|
use strict; |
251 |
|
|
my(@AoA, @tmp); |
252 |
|
|
while (<>) { |
253 |
|
|
@tmp = split; |
254 |
|
|
push @AoA, [ @tmp ]; |
255 |
|
|
} |
256 |
|
|
|
257 |
|
|
=begin original |
258 |
|
|
|
259 |
|
|
Of course, you don't need the temporary array to have a name at all: |
260 |
|
|
|
261 |
|
|
=end original |
262 |
|
|
|
263 |
|
|
もちろん、一時的な配列もなければならないというものではありません: |
264 |
|
|
|
265 |
|
|
while (<>) { |
266 |
|
|
push @AoA, [ split ]; |
267 |
|
|
} |
268 |
|
|
|
269 |
|
|
=begin original |
270 |
|
|
|
271 |
|
|
You also don't have to use push(). You could just make a direct assignment |
272 |
|
|
if you knew where you wanted to put it: |
273 |
|
|
|
274 |
|
|
=end original |
275 |
|
|
|
276 |
|
|
また、push() を使わなくてもできます。 |
277 |
|
|
どこに押し込めたいかと言うことがわかっているのなら、直接 |
278 |
|
|
代入させることもできます: |
279 |
|
|
|
280 |
|
|
my (@AoA, $i, $line); |
281 |
|
|
for $i ( 0 .. 10 ) { |
282 |
|
|
$line = <>; |
283 |
|
|
$AoA[$i] = [ split " ", $line ]; |
284 |
|
|
} |
285 |
|
|
|
286 |
|
|
=begin original |
287 |
|
|
|
288 |
|
|
or even just |
289 |
|
|
|
290 |
|
|
=end original |
291 |
|
|
|
292 |
|
|
あるいはこういう風にもできます: |
293 |
|
|
|
294 |
|
|
my (@AoA, $i); |
295 |
|
|
for $i ( 0 .. 10 ) { |
296 |
|
|
$AoA[$i] = [ split " ", <> ]; |
297 |
|
|
} |
298 |
|
|
|
299 |
|
|
=begin original |
300 |
|
|
|
301 |
|
|
You should in general be leery of using functions that could |
302 |
|
|
potentially return lists in scalar context without explicitly stating |
303 |
|
|
such. This would be clearer to the casual reader: |
304 |
|
|
|
305 |
|
|
=end original |
306 |
|
|
|
307 |
|
|
本当にそうしたいときを除き、スカラコンテキストでリストを返すかもしれない |
308 |
|
|
関数を使ってしまう可能性に気をつけるべきです。 |
309 |
|
|
これは普通の読み手には明らかでしょう: |
310 |
|
|
|
311 |
|
|
my (@AoA, $i); |
312 |
|
|
for $i ( 0 .. 10 ) { |
313 |
|
|
$AoA[$i] = [ split " ", scalar(<>) ]; |
314 |
|
|
} |
315 |
|
|
|
316 |
|
|
=begin original |
317 |
|
|
|
318 |
|
|
If you wanted to have a $ref_to_AoA variable as a reference to an array, |
319 |
|
|
you'd have to do something like this: |
320 |
|
|
|
321 |
|
|
=end original |
322 |
|
|
|
323 |
|
|
配列へのリファレンスとして変数 $ref_to_AoA を使いたいというのであれば、 |
324 |
|
|
以下の様にする必要があるでしょう: |
325 |
|
|
|
326 |
|
|
while (<>) { |
327 |
|
|
push @$ref_to_AoA, [ split ]; |
328 |
|
|
} |
329 |
|
|
|
330 |
|
|
=begin original |
331 |
|
|
|
332 |
|
|
Now you can add new rows. What about adding new columns? If you're |
333 |
|
|
dealing with just matrices, it's often easiest to use simple assignment: |
334 |
|
|
|
335 |
|
|
=end original |
336 |
|
|
|
337 |
|
|
これで新しい行を追加することができます。 |
338 |
|
|
新しいカラムを追加するのは? |
339 |
|
|
あなたがまさに行列を扱っているのなら、大概は単純な代入となります: |
340 |
|
|
|
341 |
|
|
for $x (1 .. 10) { |
342 |
|
|
for $y (1 .. 10) { |
343 |
|
|
$AoA[$x][$y] = func($x, $y); |
344 |
|
|
} |
345 |
|
|
} |
346 |
|
|
|
347 |
|
|
for $x ( 3, 7, 9 ) { |
348 |
|
|
$AoA[$x][20] += func2($x); |
349 |
|
|
} |
350 |
|
|
|
351 |
|
|
=begin original |
352 |
|
|
|
353 |
|
|
It doesn't matter whether those elements are already |
354 |
|
|
there or not: it'll gladly create them for you, setting |
355 |
|
|
intervening elements to C<undef> as need be. |
356 |
|
|
|
357 |
|
|
=end original |
358 |
|
|
|
359 |
|
|
これは対象となる要素が既に存在しているかどうかには影響されません: |
360 |
|
|
(ない場合でも)喜んであなたのためにその要素を作り出し、必要に応じて |
361 |
|
|
間にある要素に C<undef> をセットします。 |
362 |
|
|
|
363 |
|
|
=begin original |
364 |
|
|
|
365 |
|
|
If you wanted just to append to a row, you'd have |
366 |
|
|
to do something a bit funnier looking: |
367 |
|
|
|
368 |
|
|
=end original |
369 |
|
|
|
370 |
|
|
あなたは、単に行に追加したいだけという場合であっても、 |
371 |
|
|
ちょっと妙に見えることをしなければならないでしょう: |
372 |
|
|
|
373 |
|
|
=begin original |
374 |
|
|
|
375 |
|
|
# add new columns to an existing row |
376 |
|
|
push @{ $AoA[0] }, "wilma", "betty"; # explicit deref |
377 |
|
|
|
378 |
|
|
=end original |
379 |
|
|
|
380 |
|
|
# add new columns to an existing row |
381 |
|
|
push @{ $AoA[0] }, "wilma", "betty"; # 明示的デリファレンス |
382 |
|
|
|
383 |
|
|
=head2 Access and Printing |
384 |
|
|
|
385 |
|
|
(アクセスと表示) |
386 |
|
|
|
387 |
|
|
=begin original |
388 |
|
|
|
389 |
|
|
Now it's time to print your data structure out. How |
390 |
|
|
are you going to do that? Well, if you want only one |
391 |
|
|
of the elements, it's trivial: |
392 |
|
|
|
393 |
|
|
=end original |
394 |
|
|
|
395 |
|
|
こんどはこのデータ構造を出力する番です。 |
396 |
|
|
あなたはどうやろうと考えてますか? |
397 |
|
|
そうですね、簡単に要素を一つだけ出力したいとするとこうなります: |
398 |
|
|
|
399 |
|
|
print $AoA[0][0]; |
400 |
|
|
|
401 |
|
|
=begin original |
402 |
|
|
|
403 |
|
|
If you want to print the whole thing, though, you can't |
404 |
|
|
say |
405 |
|
|
|
406 |
|
|
=end original |
407 |
|
|
|
408 |
|
|
配列の内容全部を出力したいとき、次のようには書けません。 |
409 |
|
|
|
410 |
|
|
=begin original |
411 |
|
|
|
412 |
|
|
print @AoA; # WRONG |
413 |
|
|
|
414 |
|
|
=end original |
415 |
|
|
|
416 |
|
|
print @AoA; # 間違い |
417 |
|
|
|
418 |
|
|
=begin original |
419 |
|
|
|
420 |
|
|
because you'll get just references listed, and perl will never |
421 |
|
|
automatically dereference things for you. Instead, you have to |
422 |
|
|
roll yourself a loop or two. This prints the whole structure, |
423 |
|
|
using the shell-style for() construct to loop across the outer |
424 |
|
|
set of subscripts. |
425 |
|
|
|
426 |
|
|
=end original |
427 |
|
|
|
428 |
|
|
なぜなら、これでは単にリストへのリファレンスが取れるだけで、 |
429 |
|
|
perl はそれを自動的に参照外しするようなことはしないからです。 |
430 |
|
|
このため、あなたは自分自身でループしなければなりません。 |
431 |
|
|
これは外側の添え字に対するループでシェルスタイルの for() を使って |
432 |
|
|
構造全体を出力します。 |
433 |
|
|
|
434 |
|
|
for $aref ( @AoA ) { |
435 |
|
|
say "\t [ @$aref ],"; |
436 |
|
|
} |
437 |
|
|
|
438 |
|
|
=begin original |
439 |
|
|
|
440 |
|
|
If you wanted to keep track of subscripts, you might do this: |
441 |
|
|
|
442 |
|
|
=end original |
443 |
|
|
|
444 |
|
|
添え字を記録したいのなら、このようにできます: |
445 |
|
|
|
446 |
|
|
for $i ( 0 .. $#AoA ) { |
447 |
|
|
say "\t elt $i is [ @{$AoA[$i]} ],"; |
448 |
|
|
} |
449 |
|
|
|
450 |
|
|
=begin original |
451 |
|
|
|
452 |
|
|
or maybe even this. Notice the inner loop. |
453 |
|
|
|
454 |
|
|
=end original |
455 |
|
|
|
456 |
|
|
あるいはこのようなやり方もあります。 |
457 |
|
|
内側のループに注目してください。 |
458 |
|
|
|
459 |
|
|
for $i ( 0 .. $#AoA ) { |
460 |
|
|
for $j ( 0 .. $#{$AoA[$i]} ) { |
461 |
|
|
say "elt $i $j is $AoA[$i][$j]"; |
462 |
|
|
} |
463 |
|
|
} |
464 |
|
|
|
465 |
|
|
=begin original |
466 |
|
|
|
467 |
|
|
As you can see, it's getting a bit complicated. That's why |
468 |
|
|
sometimes is easier to take a temporary on your way through: |
469 |
|
|
|
470 |
|
|
=end original |
471 |
|
|
|
472 |
|
|
見て判るようにこれは少々複雑です。 |
473 |
|
|
しかし、途中で一時変数を使えば簡単にできます: |
474 |
|
|
|
475 |
|
|
for $i ( 0 .. $#AoA ) { |
476 |
|
|
$aref = $AoA[$i]; |
477 |
|
|
for $j ( 0 .. $#{$aref} ) { |
478 |
|
|
say "elt $i $j is $AoA[$i][$j]"; |
479 |
|
|
} |
480 |
|
|
} |
481 |
|
|
|
482 |
|
|
=begin original |
483 |
|
|
|
484 |
|
|
Hmm... that's still a bit ugly. How about this: |
485 |
|
|
|
486 |
|
|
=end original |
487 |
|
|
|
488 |
|
|
うーんまだちょっと見にくいですね。 |
489 |
|
|
これでどうでしょう: |
490 |
|
|
|
491 |
|
|
for $i ( 0 .. $#AoA ) { |
492 |
|
|
$aref = $AoA[$i]; |
493 |
|
|
$n = @$aref - 1; |
494 |
|
|
for $j ( 0 .. $n ) { |
495 |
|
|
say "elt $i $j is $AoA[$i][$j]"; |
496 |
|
|
} |
497 |
|
|
} |
498 |
|
|
|
499 |
|
|
=begin original |
500 |
|
|
|
501 |
|
|
When you get tired of writing a custom print for your data structures, |
502 |
|
|
you might look at the standard L<Dumpvalue> or L<Data::Dumper> modules. |
503 |
|
|
The former is what the Perl debugger uses, while the latter generates |
504 |
|
|
parsable Perl code. For example: |
505 |
|
|
|
506 |
|
|
=end original |
507 |
|
|
|
508 |
|
|
あなたのデータ構造のためのカスタム print を書くのに疲れたなら、 |
509 |
|
|
標準の L<Dumpvalue> モジュールや L<Data::Dumper> モジュールを |
510 |
|
|
見るとよいでしょう。 |
511 |
|
|
前者は Perl デバッガが使っていて、後者は Perl コードとしてパース可能なものを |
512 |
|
|
出力します。 |
513 |
|
|
例えば: |
514 |
|
|
|
515 |
|
|
use v5.14; # using the + prototype, new to v5.14 |
516 |
|
|
|
517 |
|
|
sub show(+) { |
518 |
|
|
require Dumpvalue; |
519 |
|
|
state $prettily = new Dumpvalue:: |
520 |
|
|
tick => q("), |
521 |
|
|
compactDump => 1, # comment these two lines |
522 |
|
|
# out |
523 |
|
|
veryCompact => 1, # if you want a bigger |
524 |
|
|
# dump |
525 |
|
|
; |
526 |
|
|
dumpValue $prettily @_; |
527 |
|
|
} |
528 |
|
|
|
529 |
|
|
# Assign a list of array references to an array. |
530 |
|
|
my @AoA = ( |
531 |
|
|
[ "fred", "barney" ], |
532 |
|
|
[ "george", "jane", "elroy" ], |
533 |
|
|
[ "homer", "marge", "bart" ], |
534 |
|
|
); |
535 |
|
|
push @{ $AoA[0] }, "wilma", "betty"; |
536 |
|
|
show @AoA; |
537 |
|
|
|
538 |
|
|
=begin original |
539 |
|
|
|
540 |
|
|
will print out: |
541 |
|
|
|
542 |
|
|
=end original |
543 |
|
|
|
544 |
|
|
これは以下のものを出力します: |
545 |
|
|
|
546 |
|
|
0 0..3 "fred" "barney" "wilma" "betty" |
547 |
|
|
1 0..2 "george" "jane" "elroy" |
548 |
|
|
2 0..2 "homer" "marge" "bart" |
549 |
|
|
|
550 |
|
|
=begin original |
551 |
|
|
|
552 |
|
|
Whereas if you comment out the two lines I said you might wish to, |
553 |
|
|
then it shows it to you this way instead: |
554 |
|
|
|
555 |
|
|
=end original |
556 |
|
|
|
557 |
|
|
一方、そうしたいかもしれないと書いた二つの行をコメントアウトすると、 |
558 |
|
|
代わりに以下のようなものが出力されます: |
559 |
|
|
|
560 |
|
|
0 ARRAY(0x8031d0) |
561 |
|
|
0 "fred" |
562 |
|
|
1 "barney" |
563 |
|
|
2 "wilma" |
564 |
|
|
3 "betty" |
565 |
|
|
1 ARRAY(0x803d40) |
566 |
|
|
0 "george" |
567 |
|
|
1 "jane" |
568 |
|
|
2 "elroy" |
569 |
|
|
2 ARRAY(0x803e10) |
570 |
|
|
0 "homer" |
571 |
|
|
1 "marge" |
572 |
|
|
2 "bart" |
573 |
|
|
|
574 |
|
|
=head2 Slices |
575 |
|
|
|
576 |
|
|
(スライス) |
577 |
|
|
|
578 |
|
|
=begin original |
579 |
|
|
|
580 |
|
|
If you want to get at a slice (part of a row) in a multidimensional |
581 |
|
|
array, you're going to have to do some fancy subscripting. That's |
582 |
|
|
because while we have a nice synonym for single elements via the |
583 |
|
|
pointer arrow for dereferencing, no such convenience exists for slices. |
584 |
|
|
|
585 |
|
|
=end original |
586 |
|
|
|
587 |
|
|
多次元配列のスライス(行部分)を取りたいのであれば、ややおかしな添え字付けを |
588 |
|
|
する必要があるでしょう。 |
589 |
|
|
これは参照外しのための参照の矢印を使った単一の要素に対するものは |
590 |
|
|
あるのですが、それに対応するスライス用の便利なものはないのです。 |
591 |
|
|
|
592 |
|
|
=begin original |
593 |
|
|
|
594 |
|
|
Here's how to do one operation using a loop. We'll assume an @AoA |
595 |
|
|
variable as before. |
596 |
|
|
|
597 |
|
|
=end original |
598 |
|
|
|
599 |
|
|
以下は、ループを使った一つの操作をどのように行うかの例です。 |
600 |
|
|
変数 @AoA が前のものと同じであると仮定しています。 |
601 |
|
|
|
602 |
|
|
@part = (); |
603 |
|
|
$x = 4; |
604 |
|
|
for ($y = 7; $y < 13; $y++) { |
605 |
|
|
push @part, $AoA[$x][$y]; |
606 |
|
|
} |
607 |
|
|
|
608 |
|
|
=begin original |
609 |
|
|
|
610 |
|
|
That same loop could be replaced with a slice operation: |
611 |
|
|
|
612 |
|
|
=end original |
613 |
|
|
|
614 |
|
|
このループをスライス演算に置き換えることができます: |
615 |
|
|
|
616 |
|
|
@part = @{$AoA[4]}[7..12]; |
617 |
|
|
|
618 |
|
|
=begin original |
619 |
|
|
|
620 |
|
|
or spaced out a bit: |
621 |
|
|
|
622 |
|
|
=end original |
623 |
|
|
|
624 |
|
|
または少し空白を入れると: |
625 |
|
|
|
626 |
|
|
@part = @{ $AoA[4] } [ 7..12 ]; |
627 |
|
|
|
628 |
|
|
=begin original |
629 |
|
|
|
630 |
|
|
But as you might well imagine, this can get pretty rough on the reader. |
631 |
|
|
|
632 |
|
|
=end original |
633 |
|
|
|
634 |
|
|
あなたも見て感じるかもしれませんが、これは読み手にはちょっと不親切です。 |
635 |
|
|
|
636 |
|
|
=begin original |
637 |
|
|
|
638 |
|
|
Ah, but what if you wanted a I<two-dimensional slice>, such as having |
639 |
|
|
$x run from 4..8 and $y run from 7 to 12? Hmm... here's the simple way: |
640 |
|
|
|
641 |
|
|
=end original |
642 |
|
|
|
643 |
|
|
あー、でも、$x を 4..8、$y を 7 から 12 とするような I<二次元のスライス> を |
644 |
|
|
必要とするときには? |
645 |
|
|
うーん、単純なやり方はこうでしょう。 |
646 |
|
|
|
647 |
|
|
@newAoA = (); |
648 |
|
|
for ($startx = $x = 4; $x <= 8; $x++) { |
649 |
|
|
for ($starty = $y = 7; $y <= 12; $y++) { |
650 |
|
|
$newAoA[$x - $startx][$y - $starty] = $AoA[$x][$y]; |
651 |
|
|
} |
652 |
|
|
} |
653 |
|
|
|
654 |
|
|
=begin original |
655 |
|
|
|
656 |
|
|
We can reduce some of the looping through slices |
657 |
|
|
|
658 |
|
|
=end original |
659 |
|
|
|
660 |
|
|
スライスを使ってループを簡単にできます: |
661 |
|
|
|
662 |
|
|
for ($x = 4; $x <= 8; $x++) { |
663 |
|
|
push @newAoA, [ @{ $AoA[$x] } [ 7..12 ] ]; |
664 |
|
|
} |
665 |
|
|
|
666 |
|
|
=begin original |
667 |
|
|
|
668 |
|
|
If you were into Schwartzian Transforms, you would probably |
669 |
|
|
have selected map for that |
670 |
|
|
|
671 |
|
|
=end original |
672 |
|
|
|
673 |
|
|
あなたがシュワルツ変換に興味を持っているのなら、map を使って次のように |
674 |
|
|
することを選ぶかもしれません: |
675 |
|
|
|
676 |
|
|
@newAoA = map { [ @{ $AoA[$_] } [ 7..12 ] ] } 4 .. 8; |
677 |
|
|
|
678 |
|
|
=begin original |
679 |
|
|
|
680 |
|
|
Although if your manager accused you of seeking job security (or rapid |
681 |
|
|
insecurity) through inscrutable code, it would be hard to argue. :-) |
682 |
|
|
If I were you, I'd put that in a function: |
683 |
|
|
|
684 |
|
|
=end original |
685 |
|
|
|
686 |
|
|
あなたの上司が不可解なコードによるジョブセキュリティ(もしくは急激な不安)の |
687 |
|
|
追求を非難していたとしても、説得するのは難しいでしょうね。 |
688 |
|
|
:-) もし私があなたの立場だったら、こういった操作は関数に押し込めるでしょう。 |
689 |
|
|
|
690 |
|
|
=begin original |
691 |
|
|
|
692 |
|
|
@newAoA = splice_2D( \@AoA, 4 => 8, 7 => 12 ); |
693 |
|
|
sub splice_2D { |
694 |
|
|
my $lrr = shift; # ref to array of array refs! |
695 |
|
|
my ($x_lo, $x_hi, |
696 |
|
|
$y_lo, $y_hi) = @_; |
697 |
|
|
|
698 |
|
|
=end original |
699 |
|
|
|
700 |
|
|
@newAoA = splice_2D( \@AoA, 4 => 8, 7 => 12 ); |
701 |
|
|
sub splice_2D { |
702 |
|
|
my $lrr = shift; # リファレンスのリストのリストへのリファレンス! |
703 |
|
|
my ($x_lo, $x_hi, |
704 |
|
|
$y_lo, $y_hi) = @_; |
705 |
|
|
|
706 |
|
|
return map { |
707 |
|
|
[ @{ $lrr->[$_] } [ $y_lo .. $y_hi ] ] |
708 |
|
|
} $x_lo .. $x_hi; |
709 |
|
|
} |
710 |
|
|
|
711 |
|
|
=head1 SEE ALSO |
712 |
|
|
|
713 |
|
|
L<perldata>, L<perlref>, L<perldsc> |
714 |
|
|
|
715 |
|
|
=head1 AUTHOR |
716 |
|
|
|
717 |
|
|
Tom Christiansen <F<tchrist@perl.com>> |
718 |
|
|
|
719 |
|
|
Last update: Tue Apr 26 18:30:55 MDT 2011 |
720 |
|
|
|
721 |
|
|
=begin meta |
722 |
|
|
|
723 |
|
|
Translate: KIMURA Koichi (5.005_03) |
724 |
|
|
Update: SHIRAKATA Kentaro <argrath@ub32.org> (5.6.1-) |
725 |
|
|
Status: completed |
726 |
|
|
|
727 |
|
|
=end meta |
728 |
|
|
|