« Linuxで仮想CDドライブ | トップページ | IPv6を停止する - Vine Linux 4.1 »

2007-07-20

ハッシュの値に配列を格納する

Perlでも多次元配列が使いたい場合などは、多々あります。
できれば連想配列(ハッシュ)の値に配列を格納できると、
更に便利に使えると思います。
CSVファイルのデータを、特定のキーごとにまとめる際などには
役に立つのではないでしょうか。

#
# 配列chiba, saitamaの初期化
#
@chiba = (
  '千葉市',
  '市川市',
  '佐倉市',
  '長生郡');

@saitama = (
  '草加市',
  '川口市',
  '北本市');

#
# ハッシュの値として配列を代入
#
@{$hash{'千葉県'}} = @chiba;
@{$hash{'埼玉県'}} = @saitama;

#
# キーが千葉県のハッシュの値(配列)の要素として、
# 茂原市を追加
#
push(@{$hash{'千葉県'}}, '茂原市');

#
# ハッシュ内のデータを全出力
#
#
# ハッシュをキーと値に分ける
while (($pref, $city) = each(%hash)) {
  #
  # ハッシュの値(配列)を全て巡回する
  foreach (@{$city}) {
    print "$pref$_\n"; # 出力
  }
  print "\n"; # ハッシュ毎に空行を入れる
}
ハッシュの値に配列を
ごっそり代入する場合に、
一般的には配列のリファレンスを利用します。
$hash{'千葉県'} = \@chiba;
のようにしますが、ここではリファレンスを代入するよりも、
デリファレンスした配列に配列をコピーする方が分かりやすい気がしたので、
@{$hash{'千葉県'}} = @chiba;
のように、ハッシュの値を配列型にしてから、
代入しました。

こういう場合、一般的には配列の無名リファレンスを使って、
以下のようにするんじゃないかと思います。
%hash = ('千葉県' => ['千葉市', '市川市', '佐倉市', '長生郡'], '埼玉県' => ['草加市', '川口市', '北本市']);

この書き方だと、何をどうしているのか理解しづらいと思います。
簡単に配列を代入できていて、ハッシュから値を取り出す時にも、
配列が返ってきそうな感じするのではないかと思いました。
実際には、@copy_array = $hash{'千葉県'};
のようにすると、@copy_array配列に配列のリファレンスを格納した事になってしまいます。
print ref($hash{'千葉県'});とすると、
$hash{'千葉県'}がリファレンスであり、指しているオブジェクトが配列(ARRAY)である事がわかります。
ref関数は、パラメータが非リファレンスの場合には、偽を返します。

また、デリファレンスの際に通常の感じで、@$hash{'千葉県'}のようにすると、
@$hashとしたように扱われているのではないかと思います。
こうなってしまうと、$hashが配列のレファレンスという意味になってしまい、
$hash->[0];というような事ができる事になってしまいます。
$hashはリファレンスではなく、ハッシュなのでおかしな事になってしまいます。
なので、{ }でデリファレンスする範囲が$hash{'千葉県'}である事を明確にします。
ハッシュや配列のリファレンスでなくても、デリファレンスで必ず{ }をつけても大丈夫だと思います。
サブルーチンのリファレンスに対して&{$func}($param);としてみましたが、
正常に動きました。
特定の要素を、
特定のハッシュの値に追加する場合には、
push(@{$hash{'千葉県'}}, '茂原市');
のように、push関数を利用して、追加します。
この時、受取り側のハッシュは、
代入の時と同じように、
配列型にデリファレンスしておきます。
配列の値を持つハッシュをeach関数で、
キーと値に分ける場合は、
値もスカラー変数として、受け取る事になるので、
受け取った後で、配列型として扱う必要があります。
その為に、foreach文のパラメータは、
@{$city}としてアクセスしています。
このサンプルの実行結果は、
以下のようになります。
埼玉県草加市
埼玉県川口市
埼玉県北本市

千葉県千葉市
千葉県市川市
千葉県佐倉市
千葉県長生郡
千葉県茂原市

|

« Linuxで仮想CDドライブ | トップページ | IPv6を停止する - Vine Linux 4.1 »

Perl」カテゴリの記事

コメント

はじめまして。

push(@{$hash{'千葉県'}}の@{}の記法が長年
分かりませんでした。このブログでやっと解決
しました!ありがとうございました。

ところで、この記法はどの書籍に記されていた
のでしょうか?教えて頂けると幸いです。
よろしくお願いいたします。

投稿: Smoodh! | 2009-07-01 06:29

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: ハッシュの値に配列を格納する:

« Linuxで仮想CDドライブ | トップページ | IPv6を停止する - Vine Linux 4.1 »