第4章 ハッシュ変数
4-1. ハッシュ変数とは
ハッシュとは、連想配列とも呼ばれ、「キー」と「値」を1組のペアとして関連付けされた配列です。
ただし、配列自体は順序付けされていないところに特徴があります。
ハッシュの変数のことを、ハッシュ変数といい、% (パーセント) + 英字1文字から始まり、それ以降は数字、英字およびアンダースコア ( _ ) を用いることができます。また大文字と小文字が区別されますので、たとえば %a と %A は別物として扱われます。
4-2. ハッシュ変数の操作
ハッシュ変数は、キーと値をペアにして、数値や文字列を代入します。
上記の場合、red(キー)とapple(値)というペアと、yellow(キー)とbanana(値)というペアを、それぞれ%fruitに代入します。
1 | %fruit = ( "red" => "apple" , "yellow" => "banana" ); |
ハッシュ変数の中の各要素(各ペア)は、$ハッシュ変数名 { キー } という形式で、それに対応する「値」を参照することができます。
したがって、前述の%fruitは、以下のように記述することもできます。
したがって、前述の%fruitは、以下のように記述することもできます。
1 | $fruit { "red" } = "apple" ; |
2 | $fruit { "yellow" } = "banana" ; |
ハッシュ変数の各要素には、「キー」を指定することで「値」にアクセスすることができます。
1 | %fruit = ( "red" => "apple" , "yellow" => "banana" , "purple" => "grape" ); |
2 | print "$fruit{'red'}\n" ; |
1 | > apple |
ちなみに、「キー」の文字列が全て「英数字・アンダースコア」の場合には、クォーテーションによる括りを省略しても構いません。
ちょっとしたことですが、結構便利です。
1 | # キーのクォーテーションを省略した例-1 |
2 | %fruit = (red => "apple" , yellow => "banana" , purple => "grape" ); |
3 |
4 | # キーのクォーテーションを省略した例-2 |
5 | print "$fruit{red}\n" ; |
4-3. ハッシュ関数
ハッシュを操作するための関数として、次のような関数が用意されています。
関数 | 内容 |
---|---|
keys | すべてのキーを取り出す |
values | すべての値を取り出す |
each | 1組のキーと値を取り出す |
delete | 特定の要素を取り除く |
1. keys
すべての「キー」を取り出します。
ただし、取り出された配列の順序は一定でないことに注意します。 これはハッシュが順序付けられた配列ではないためです。
ただし、取り出された配列の順序は一定でないことに注意します。 これはハッシュが順序付けられた配列ではないためです。
1 | %fruit = (red => "apple" , yellow => "banana" , purple => "grape" ); |
2 | @file = keys %fruit ; |
3 |
4 | print "@file\n" ; |
1 | > purple yellow red |
2. values
すべての「値」を取り出します。
keys関数同様、取り出された配列の順序は一定ではありません。
keys関数同様、取り出された配列の順序は一定ではありません。
1 | %fruit = (red => "apple" , yellow => "banana" , purple => "grape" ); |
2 | @file = values %fruit ; |
3 |
4 | print "@file\n" ; |
1 | > grape banana apple |
3. each
1組の「キー」と「値」を取り出します。
1 | %fruit = (red => "apple" , yellow => "banana" , purple => "grape" ); |
2 | ( $key , $val ) = each %fruit ; |
3 |
4 | print "$key : $val\n" ; |
1 | > purple : grape |
しかしながら、上記の場合、どのペアが取り出されるかが不定であり、しかも1組だけが抽出されるので、通常each関数の場合は次のようにwhile構文と併用した形で使用されます。
1 | %fruit = (red => "apple" , yellow => "banana" , purple => "grape" ); |
2 |
3 | # ハッシュの全要素を展開 |
4 | while ( my ( $key , $val ) = each %fruit ) { |
5 | print "$key : $val\n" ; |
6 | } |
1 | > purple : grape |
2 | > yellow : banana |
3 | > red : apple |
4. delete
ちなみに、上記のdelete関数は特定の要素を削除する場合ですが、全要素を削除する場合には、空リストを代入すると、全要素が削除されます。
ただし、上記の場合中身が空ですが、定義値のままです。
もし、未定義値にしたい場合には、undef関数を使用します。
特定の要素を取り除きます。
変数によるキーを指定することで、そのキーと値のペアをハッシュから削除します。
変数によるキーを指定することで、そのキーと値のペアをハッシュから削除します。
1 | %fruit = (red => "apple" , yellow => "banana" , purple => "grape" ); |
2 |
3 | # 要素を削除(yellow - banana の要素) |
4 | delete $fruit {yellow}; |
5 |
6 | # 残りの要素を全て展開 |
7 | while ( my ( $key , $val ) = each %fruit ) { |
8 | print "$key : $val\n" ; |
9 | } |
1 | > purple : grape |
2 | > red : apple |
1 | %fruit = (); |
1 | undef %fruit ; |
4-4. ハッシュスライス
配列変数に対する場合と同様に、ハッシュのスライスを使用すれば、各要素の集合にアクセスすることができます。
たとえば、次のようなメンバーの年齢データがあったとします。
これをスライスを使うと、次のように記述できます。先頭が、%ではなく@であることに注意してください。
以下に、コード例で見てみましょう。
tomとmikeが今月誕生日を迎えました。年齢を更新してみましょう。
また、スライスを使うことで、任意の要素の値をリストとして取り出すこともできます。
1 | %age = (tom => 21, mike => 19, kent => 25, nancy => 17); |
1 | @age { qw(tom mike kent nancy) } = (21,19,25,17); |
tomとmikeが今月誕生日を迎えました。年齢を更新してみましょう。
01 | use strict; |
02 |
03 | # 年齢データ |
04 | my %age = (tom => 21, mike => 19, kent => 25, nancy => 17); |
05 |
06 | # tomとmikeを更新 |
07 | @age { qw(tom mike) } = (22,20); |
08 |
09 | # データの中身を見る |
10 | while ( my ( $key , $val ) = each %age ) { |
11 | print "$key : $val\n" ; |
12 | } |
1 | > nancy : 17 |
2 | > kent : 25 |
3 | > tom : 22 |
4 | > mike : 20 |
01 | use strict; |
02 |
03 | # 年齢データ |
04 | my %age = (tom => 21, mike => 19, kent => 25, nancy => 17); |
05 |
06 | # kentとnancyの年齢を取り出す |
07 | my @data = @age { qw(kent nancy) }; |
08 |
09 | # リストの中身を見る |
10 | print "@data\n" ; |
1 | > 25 17 |
4-5. ハッシュを代入順に並べる
ハッシュの配列は、順番どおりには並ばないことは前に述べました。
しかしながら、どうしてもキーや値を順番通りに取り出したい場合には、実はTie::IxHashモジュールを利用することで実現できます。
使い方によっては、大変便利なモジュールですので、ご紹介しておきます。
しかしながら、どうしてもキーや値を順番通りに取り出したい場合には、実はTie::IxHashモジュールを利用することで実現できます。
使い方によっては、大変便利なモジュールですので、ご紹介しておきます。
Tie::IxHashの使い方のポイントは、必ず対象のハッシュを呼び出す前に、tie関数で関連付けしておきます。
上記のように、全てのキーと値を代入順に取り出すことができます。
01 | use strict; |
02 | use Tie::IxHash; |
03 |
04 | # %hashを関連付け |
05 | tie ( my %hash , 'Tie::IxHash' ); |
06 |
07 | # ハッシュに代入 |
08 | %hash = ( |
09 | Sun => 0, |
10 | Mon => 1, |
11 | Tue => 2, |
12 | Wed => 3, |
13 | ); |
14 |
15 | # 全要素を展開 |
16 | while ( my ( $key , $val ) = each %hash ) { |
17 | print "$key : $val\n" ; |
18 | } |
1 | > Sun : 0 |
2 | > Mon : 1 |
3 | > Tue : 2 |
4 | > Wed : 3 |
ちなみに、Tie::IxHashモジュールは標準モジュールではありませんので、各自でインストールする必要があります。
ただし、PurePerl(すべてPerl言語で書かれたもの)のため、Perlライブラリ(jcode.pl, cgi-lib.pl等)のように、ホームディレクトリの中に置いて使用することが可能です。
ただし、PurePerl(すべてPerl言語で書かれたもの)のため、Perlライブラリ(jcode.pl, cgi-lib.pl等)のように、ホームディレクトリの中に置いて使用することが可能です。
参考 : 【コラム】Perlモジュールの組み込み
4-6. 多次元ハッシュ
ハッシュは、配列と同様に多次元に展開させることができます。ハッシュの中にハッシュを作ることができます。
以下のハッシュは、いわゆる二次元ハッシュになります。
波括弧(ブレース)の部分を、1つのスカラーと読み替えると、分かりやすいかもしれません。
1 | %hash = ( |
2 | A => { a => 1, b => 2, c => 3 }, |
3 | B => { d => 4, e => 5, f => 6 }, |
4 | ); |
%hashにおいて、キー「A」に対する値の中の最初のキー「a」の値「1」にアクセスするには、添字を使用して次のように記述することができます。
リファレンスを使って、キー「A」に対する値(配列)を展開するには、次のように記述します。
%hashの中の全てのキーと値を展開するには、次のように記述します。
%hashに対して、二次元のキーと値をさらに追加してみましょう。
特定のキーに対する値に、要素を追加してみましょう。
1 | %hash = ( |
2 | A => { a => 1, b => 2, c => 3 }, |
3 | B => { d => 4, e => 5, f => 6 }, |
4 | ); |
5 |
6 | print "$hash{A}{a}\n" ; |
1 | > 1 |
1 | %hash = ( |
2 | A => { a => 1, b => 2, c => 3 }, |
3 | B => { d => 4, e => 5, f => 6 }, |
4 | ); |
5 |
6 | while ( my ( $key , $val ) = each %{ $hash {A}} ) { |
7 | print "$key : $val\n" ; |
8 | } |
1 | > c : 3 |
2 | > a : 1 |
3 | > b : 2 |
01 | %hash = ( |
02 | A => { a => 1, b => 2, c => 3 }, |
03 | B => { d => 4, e => 5, f => 6 }, |
04 | ); |
05 |
06 | foreach my $tmp ( keys %hash ) { |
07 | while ( my ( $key , $val ) = each %{ $hash { $tmp }} ) { |
08 | print "$key : $val\n" ; |
09 | } |
10 | } |
1 | > c : 3 |
2 | > a : 1 |
3 | > b : 2 |
4 | > e : 5 |
5 | > d : 4 |
6 | > f : 6 |
01 | %hash = ( |
02 | A => { a => 1, b => 2, c => 3 }, |
03 | B => { d => 4, e => 5, f => 6 }, |
04 | ); |
05 |
06 | # キー「C」に対する二次元の値を追加 |
07 | $hash {C} = { g => 7, h => 8, i => 9 }; |
08 |
09 | while ( my ( $key , $val ) = each %{ $hash {C}} ) { |
10 | print "$key : $val\n" ; |
11 | } |
1 | > h : 8 |
2 | > g : 7 |
3 | > i : 9 |
01 | %hash = ( |
02 | A => { a => 1, b => 2, c => 3 }, |
03 | B => { d => 4, e => 5, f => 6 }, |
04 | ); |
05 |
06 | # キー「A」に対する値に要素追加 |
07 | $hash {A}{x} = 7; |
08 |
09 | while ( my ( $key , $val ) = each %{ $hash {A}} ) { |
10 | print "$key : $val\n" ; |
11 | } |
1 | > c : 3 |
2 | > a : 1 |
3 | > b : 2 |
4 | > x : 7 |