ハッシュを使いこなそう

 Perlには「ハッシュ(連想配列)」という便利なデータ構造があります。ハッシュは配列に似ています。同じことを配列とハッシュの両方で実現できる場合は多くありますが,ほとんどの場合ハッシュの方が有用なケースが多いでしょう。ぜひ覚えてください。

 ハッシュは,「キー」と「値」の組み合わせを扱うデータ構造です。たとえば,お寿司それぞれの値段をいちいち

$uni_kakaku = 500;
$maguro_kakaku = 400;
$ikura_kakaku = 600;
リスト3●ハッシュを利用する例
図3●リスト3の実行結果
リスト4●条件分岐の例
図4●リスト4の実行結果
リスト5●foreach を利用して配列のすべての要素を処理する
図5●リスト5の実行結果
リスト6●each 関数とwhile を組み合わせてハッシュの要素を処理する
図6●リスト6の実行結果

のように書くのは面倒ですよね。Perlではこのようなとき,普通ハッシュを利用します(リスト3[拡大表示])。

 (12)がハッシュです。ハッシュ名の頭には%を付けます。「%」はハッシュ全体であることを意味します。「=>」は見た目の通り矢印です。矢印の左側がキー,右側が値です。このハッシュのキーはお寿司の種類,キーに対応づけられた値は金額です。

 ハッシュにアクセスするにはキーを指定します。書式は以下の通りです。

$ハッシュ名{"キー名"}

配列の場合とよく似ていますが,{ }であることに注目してください。(13)は(12)で作成したハッシュにアクセスする例です。(13)を実行すると,ハッシュ%kakakuに格納してあり,キー「uni」が示す値,つまり「500」を画面に表示します(図3[拡大表示])。同様に,(14)のように演算して合計を表示することもできます。

 ハッシュの利用で注意して欲しいのは,一つのハッシュの中で,同じキーが複数存在することがない,ということです。(15)のようにキーuniが指定する値として,現在とは異なる値を代入すると,値は上書きされます。(16)の行が実行されると画面に600と表示されます。

 ハッシュの値は,値は変数と同様に数値,文字列のどちらも扱えます。一つのハッシュに混在させることも可能です。一方,キーは文字列でなければなりません。でも

%jikken = {
 123 => "hifumi"
};

はエラーにならず,正しく処理されます。このハッシュのキーは文字列の「123」として扱われます*9。このあとで

print $jikken{123};

としても,画面には「hifumi」と表示されてしまいます。さらに,

print $jikken{124 - 1};

としても,「hifumi」と表示できます。

 Perlの数値と文字列は,必要に応じて自動的に変換されます。Perlの処理系は,「123」を,ハッシュのキーとして利用されようとしていると判断して,文字列として扱います。「124 - 1」の場合は「-」演算子があることからまず数値として処理し,得られた数値「123」を,さらにハッシュのキーとして指定されているので文字列に変換してからハッシュにアクセスしたのです。筆者は普段C言語とJavaを利用する機会が多いのですが,Perlに触れて「なんて楽なんだろう…」と最初に驚いたのはこの数値と文字列の自動変換でした。みなさんはいかがでしょうか。

条件分岐と繰り返し

 次は制御構造です。まずは条件分岐する「if」から見てみましょう(リスト4[拡大表示])。CやJavaを知っている人は,「あ,同じ!」と感じると思いますが,一応解説しておきますね。制御構造ifの書式は以下の通りです。

if(条件){
 #条件が真なら実行
} else {
 #条件が偽なら実行
}

 条件には式を利用します。条件が真の場合は,ifの直後に続く「{」から「}」までのブロックだけを実行します。条件が偽の場合はelseに続くブロックだけを実行します。

 数値を比較する場合は「数値比較演算子」が利用できます。数値比較演算子には「==」(値が等しい場合に真),「!=」(値が等しくない場合に真),「<」(左辺が右辺よりも小さい場合に真)――などがあります。リスト4(18)がif文です。変数$aと変数$bが等しいかを調べます。(17)を見ると両者は同じ値ですから,(19)の部分が実行され,画面に「equal」と表示されます(図4[拡大表示])。#で始まる行はコメント行です。

 同様に文字列も比較できますが,数値と演算子が異なります。(20)のif文で,配列の最初の要素と,2番目の要素を比較しています。「eq」(equalの略)は文字列を比較する文字列比較演算子です。数値比較演算子の「==」に相当します。「!=」に相当するのは「ne」(not equal」の略)です。(19)は文字列「uni」と文字列「maguro」が等しいかどうかを調べます。結果は等しくありませんから,画面には「not equal」と出力されます。

 次は繰り返しです。Perlで繰り返しを実現する制御構造はいくつかありますが,ここではwhileとforeachの二つを紹介します。まずwhileから見てみましょう。書式は以下のようになっています。

while(条件){
  #条件が真の間繰り返す
}

条件が真である間,ブロックの中を繰り返します。簡単ですね。

 次はforeachです。配列の要素すべてを処理する場合によく利用されます(リスト5[拡大表示])。(21)が処理対象となる配列です。(22)がforeach制御構造です。foreachに続けて,カッコの中に処理したい配列を記述します。すると,配列の要素すべてに対して,ブロック内の処理が実行されます(図5[拡大表示])。

 (23)では,見慣れない表記「$_」が出てきました。$_は「デフォルト変数」と呼びます。Perlの関数では,変数や値を指定しなかったとき,$_を利用するのが一般的です。これを知っていると,変数名を考えたり,それをキーボードで打ち込んだり,タイプミスしたりしなくて済みます。可読性は下がりますが,慣れれば便利なものなので,ぜひ活用してください。ちなみに(22)の範囲をデフォルト変数を利用せずに記述すると,

foreach $neta (@sushi){
 print $neta, "don\n";
}

となります。

 ハッシュ全体に対して繰り返しを実行したい場合もあるでしょう。このような場合はeach関数とwhile制御構造を組み合わせて利用します。

 例を見てみましょう(リスト6[拡大表示])。(22)が操作の対象となるハッシュです。(23)はちょっと難解かもしれませんので,ゆっくり説明します。まず「each %kakaku」は,ハッシュから「キー,値」の組をリストとして返します。リストという言葉は初登場ですね。ここでは,追加したり削除したりできない配列だと思ってください。最初は「(uni, 500)」という組み合わせが「($neta, $nedan)」に入ります。

 そのあと(24)を実行します。このお寿司屋さんは,うれしいことに全品半額のようです。実行が終わったら(23)に戻り,ハッシュ%kakakuの次の要素で繰り返します。繰り返す要素がなくなると,この代入式は「0」を返します。Perlで0は“偽”と判断されるため,whileループを抜けます。(25)で,半額になった価格を表示しています(図6[拡大表示])。