|
||||
|
|
3章 配列
|
|
|
配列とは
複数の値をまとめて扱う時1〜2つなら前章で説明したスカラ変数での使用で問題ないとおもいます。 しかし『100個のデータをまとめて処理したい!』と言う場合はどうすればよいのでしょう!? スカラ変数を100個用意して、値を代入していって・・・等々とても大変な作業になってしまいます。 こんな時は大抵のプログラム言語では配列と呼ばれる仕組みを利用します。
Perlで配列を使用する場合は、プレフィクス [ @ ] を変数名の前に付けます。これを付ける事でスカラ変数やその他の変数と区別します。配列の要素が同一のデータ型でなくても格納する事が可能です。 配列を使用しない場合 [ 10個の変数を初期化する ]
$a1 = '壱' ;
$a2 = '弐' ; $a3 = '参' ; $a4 = '四' ; ↓ $a10 = '壱拾' ; [ 100個の変数を表示させる ]
print $a1 ;
print $a2 ; print $a3 ; print $a4 ; ↓ print $a100 ; 配列を使用した場合 [ 10個の変数を初期化する ]
@a = ('壱','弐','参','四','伍','六','七','八','九','壱拾') ;
[ 100個の変数を表示させる ]
for ( 1 .. 100 ) {
print $a[$_] ; } 10個の変数を初期化するサンプルでは、配列変数 @a に対して値を代入しています、先頭から順に0・1・2・・・といった添字で配列へ格納されます。通常のプログラム言語では先ず配列の大きさを宣言しそれから値を代入するといった手順ですが、Perlでは配列の領域の確保をプログラマが意識する必要はありません。 配列を大きくしたりといった事は Perlが自動的に処理してくれるからです。 100個の変数を表示させるサンプルでは、配列のプレフィクス@が出てきていません。 これは配列全体に対して処理を行う場合 (先述の、10個の変数を初期化するような場合) はプレフィクス@を使用しますが、配列を構成している各要素はそれぞれスカラで構成されている為、各要素へのアクセスは通常のスカラ変数同様にプレフィクス [ $ ]を使用します。 ※ただし添字を表わす[]を忘れてしまうと全く異なる意味になってしまうので注意して下さい。 配列への代入
Perlの基本的な書き方は C言語に似ていると言われますが、その他の特徴として Perlは非常に自由度の高いコーディングをする事が出来ます。 そのため上級者の書いたコードを見てみると、こんな記述が出来るのかと思うことも良くあります。 今回は配列への代入方法としていくつかパターンを挙げてみましたので見てください。
@Array = ( 1 , 2 , 3 , 4 , 5 ) ;
$Array[0] =1 ,$Array[4] =5といった具合に先頭から順番に格納されます。
@Array = ( 1 , @Array2 , 3 ) ;
こんな代入も可能です。 先頭の $Array[0] には1が代入され、それから 配列変数 @Array2 の値がそれぞれ代入され、最後に 3 が入る事になります。
$Array[0] = "Hello World!!" ;
配列 @Arrayの先頭の要素 $Array[0] に文字列 "Hello World!!" が格納されます。
$Array[5] = "Hello World!!" ;
配列 @Arrayの5つめの要素 $Array[5] に文字列 "Hello World!!" が格納されます、しかしいきなりこのような記述をした場合、要素 0〜4番目の領域まで Perlがメモリを確保しているので領域の無駄遣いになってしまいます。
@Array[1 ,2 ,3 ,4] = ( 10 ,20 ,30 ,40 ) ;
先頭の要素は未定義になり2番目の要素から順に格納されます。 ※受取り側で代入される添字を指定している為配列の大きさは変りません。
@Array[0..1] = ( 10 ,20 ,30 ,40 ) ;
先頭の要素は10、2番目の要素が20となり残りの値は無視されます。 ※受取り側で代入される添字を指定している為配列の大きさは変りません。
@Array = ( ) ;
空の配列を作成 ( 配列の初期化 ) をします。
@Array = @Array1 ;
@Array1の複製を@Arrayとして作成します、この時@Arrayの大きさは@Array1に合わせられます。
$#Array = 2 ;
配列の大きさを変更します。 ( 上のサンプルでは $Array[0] 〜 $Array[2] の 3つの要素を保持する配列になります ) この時指定した数値より大きい添字のデータは破棄されてしまいます。 参照
上で配列への色々な代入方法を見ましたが、今回は配列に入っているデータを参照する方法をご紹介します。 サンプルで使っている配列は以下のような値が設定されているものとして見てください。
@week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ) ;
print $week[2] ;
配列の 3番目の要素 [ Tue ] を出力します。
( $s1 ,$s2 ,$s3 ) = @week ;
$s1へ先頭の 'Sun'を、 $s2へ 'Mon'を、 $s3へ 'Tue'と順にスカラ変数へ格納されます。
( $s1 ,$s2 ,$s3 ) = @week[2..4] ;
$s1へ先頭の 'Tue'を、 $s2へ 'Wed'を、 $s3へ 'Thu'と配列の参照場所を指定してスカラ変数へ格納する事も出来ます。このような使い方を 配列スライスと呼びます。
print $#week ;
$#を使用する事によって、その配列で指定できる最大の添字を参照する事が出来ます。 この配列は 0〜6の要素を持っているので、このように参照した場合返される値は [ 6 ] となります。
print @week ;
配列の全ての要素を出力します。 ただしこの時出力される文字列は区切り文字で丁寧に区切ってくれる訳ではなく、全て繋がって [ SunMonTueWedThuFriSat ] と表示されてしまいます。 コンテキスト 少し面白い例を見てみます。次のスクリプトを実行すると何が表示されるでしょうか??
@week = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ) ;
$size = @week; print $size; [ SunMonTueWedThuFriSat ] と思われた方が多いと思いますが、実はこれは [ 7 ] と表示されます。理由は Perlでは左辺 ( この例では $size ) が何を要求しているかで返る値が異なる時があるからです。つまり print文はリスト値 ( 配列 ) を右辺に要求しています。 それに対して上の例は左辺にスカラ変数を使用しているので右辺に対してもスカラ値を要求しているのです。 このためこの様な結果になった訳です。 ※この事をコンテキストと呼びます、詳しい説明は 《 追加事項 》 を参照して下さい。 回りくどい説明でしたが、 [ @配列名 ] をスカラ値で評価した時はその配列の大きさが返ります。 配列操作配列の全ての要素に処理を行う [ foreachを使用する ]
foreach $変数 ( @配列名 ) {
処理 } foreachステートメントを使用すると、毎回 [ $変数 ] へ配列の要素が 0番目から順に代入されます。 配列の要素を全て参照し終わった時点でこの foreachブロックを終了します。 [ whileを使用する ]
while ($変数 = shift ( @配列名 ) ){
処理 } 後述する shift関数と、foreach ステートメントを組み合わせて使用しています。この shift関数は、配列の先頭から順に配列から要素を取り除いていき、取り除く要素が無くなった段階で未定義を返します。 whileブロックでは 配列の要素が全て参照し終わって返されるこの未定義によって処理が終了します。 [ 平均を求めるプログラムを作ってみる ]
$sum = 0 ;
@array = (1,2,3,4,5,6,7,8,9,10); foreach $tmp (@array){ $sum+=$tmp; } $sum/=@array ; print "平均は $sumです\n"; #表示 → 平均は 5.5です foreachを使用し変数に値を足し込んで最後に平均を求めます。 今回作成したサンプルは foreachステートメントを使用していますが、 whileステートメントと shift関数では上手く動きません。 shift関数は実際に配列から要素を取り除くので、今回のサンプルで行っているような最後に配列の大きさを参照するという事が出来ないからです。 shift関数と whileステートメントで実現する場合は、事前に配列の大きさを退避しておく必要があります。 配列操作関数
shift
[取り除いた要素] = shift [配列] ;
配列の最初の要素を取り除いて、取り除いた後の配列を返します。 配列の長さを1つ短くし、残りを順にずらします。 配列中に要素が一つも無い時は未定義を返し、引数の配列を省略した時は特殊配列が使用されます。 配列を省略した時、メインプログラムでは @ARGV が、サブルーチンの中では @_ が使用されます。 unshift
[追加後の要素数] = unshift [配列] , [追加する要素] ;
第一引数に追加される配列を、第二引数に追加するリストを指定します。 この関数は要素が追加された後の配列を返します。 pop
[取り除いた要素] = pop [配列] ;
引数で指定した配列から末尾の要素を取り除き、取り除いた要素を返します。 取り除かれた配列は長さが1つ短くなります。 配列を省略した場合、メインプログラムでは @ARGV が、サブルーチンの中では @_ が使用されます。 push
[追加後の配列の長さ] = push [配列] , [追加する値] ;
popと逆の働きをします。 配列の末尾に指定された要素を追加し、追加された後の配列の長さを返します。 sort
[ ソート後のリスト ] = sort [ ソートの定義 ] [ ソート対象 ] ;
引数で指定した配列を並び替えて、ソート処理後の配列を返します。 ※デフォルトでは文字コード順 で並び替えが行われますが、他にも色々な指定が可能です。 reverse
[逆順の配列] = reverse [配列] ;
配列要素を逆順に並び替えてソート処理後の配列を返します。 join
[連結された文字列] = join [区切り文字列] , [配列] ;
配列の全要素を区切り文字で指定した文字で連結して、連結した文字列をスカラー型で返します。 split
[分割された配列] = split [区切りパターン , [分割対象文字列]] ;
文字列を区切りパターンにより分割し配列を作成します。第二引数は分割対象の文字列を指定し、第三引数は分割する最大値の指定となります。第二引数を省略した場合は $_ が使用されます。 grep
[抽出された配列] = grep ( パターン , 対象配列 ) ;
引数に与える配列からパターンにマッチする要素からなる配列を作成します。 ※条件を正規表現のパターンにて記述します( 第8章参照 ) [ サンプル ]
@foo = grep ( !/^#/ , @bar ) ; # 配列に含まれるコメント行を取り除く
コマンドライン引数 「 @ARGV 」
コマンドライン引数とは コマンドラインから、 Perlスクリプトにパラメタを渡すことが出来る仕組みの事です。 この仕組みを使えばスクリプトの動作をコマンドラインから渡した値によって変更するように汎用的にすることも出来ます。
[ コマンドライン引数受け渡しのサンプル ]
# 例えば以下のようにスクリプトを起動すると・・・
perl sample.pl April May June print $ARGV[0] ; # April が表示 print $ARGV[1] ; # May が表示 print $ARGV[2] ; # June が表示 [ 第一引数へのアクセス ]
$ARGV[0]
[ 指定できる最大の添字 ]
$#ARGV
[ 最後の引数へのアクセス ]
$ARGV[$#ARGV]
|