連想配列

■ 連想配列を使用する

◆ 連想配列とは

連想配列 は、文字列を キー とする配列です。ハッシュ とも呼ばれます。個々の要素は $連想配列名{キー} で表します。配列ではキー(添字)を [...] で囲みますが、連想配列では {...} で囲みます。

hash1.pl
$person{'Name'} = "Tanaka";
$person{'Age'} = 26;
$person{'Tel'} = "012-345-6789";

print "$person{'Name'} $person{'Age'} $person{'Tel'}\n";

実行結果は次のようになります。

Tanaka 26 012-345-6789

■ 連想配列にまとめて代入する

◆ 連想配列への一括代入

連想配列全体を %連想配列名 で表します。Perl 5では、上記のようにして、連想配列の各要素を一度に代入できるようになりました。

hash2.pl
%person = (
    Name => "Tanaka",
    Age  => 26,
    Tel  => "012-3456-7890"
);
print "$person{'Name'} $person{'Age'} $person{'Tel'}\n";

Perl 4 では次のようにして一括代入が可能です。

%person = ( "Name", "Tanaka", "Age", 26, "Tel", "012-3456-7890" );

■ 連想配列を連結する

◆ 連想配列の結合

下記のようにして、連想配列 %data1 と連想配列 %data2 を連結して、新しい連想配列 %data3 を生成することができます。

hash3.pl
%data1 = (
    "AAA" => "aaa",
    "BBB" => "bbb",
    "CCC" => "ccc"
);
%data2 = (
    "XXX" => "xxx",
    "YYY" => "yyy",
    "ZZZ" => "zzz"
);
%data3 = ( %data1, %data2 );
print "ZZZ = $data3{'ZZZ'}\n";

結果は次のようになります。

ZZZ = zzz
◆ キーが重複した場合の動作

%data1 と %data2 の中に同じキーの値が存在する場合は、後ろに指定した連想配列の値が有効になります。

hash4.pl
%data1 = (
    "AAA" => "aaa",
    "BBB" => "bbb",
    "CCC" => "ccc"
);
%data2 = (
    "CCC" => "333",
    "DDD" => "444",
    "EEE" => "555"
);
%data3 = ( %data1, %data2 );
print "CCC = $data3{'CCC'}\n";

結果は次のようになります。

CCC = 333

■ 連想配列の個々の要素について処理する(each)

◆ 連想配列の個々の要素に対する処理

each() は、連想配列のキーと値の組みを返します。each() を用いて、連想配列の個々の要素に関して処理を行うことができます。

each.pl
$data{'AAA'} = "aaa";
$data{'BBB'} = "bbb";
$data{'CCC'} = "ccc";

while (($key, $value) = each(%data)) {
    print "$key = $value\n";
}

表示結果は例えば次のようになります。

CCC = ccc
BBB = bbb
AAA = aaa
◆ 連想配列が処理される順序

連想配列が処理される順番はデタラメです。代入した順序通りにはなりませんし、キーや値の ABC順になる訳でもありません。


ひとくちメモ

Perl では連想配列をハッシュ値によるグループに分けて管理しています。ハッシュ値は例えば、「キーで使用されている文字コードをすべて足して 256 で割った値」などのハッシュアルゴリズムを用いて計算します。こうすると連想配列は 256 個のグループに分類され、値を探すときも該当グループの中だけを捜せばよいので、検索処理を高速化することができます。each() ではこのグループの順序に従って要素を返すので、見た目の順序はバラバラになります。

■ 連想配列を代入した順序通りに処理する

◆ 代入順に処理する

each(%連想配列名) を用いた場合、順序はバラバラになります。代入した順序通りに処理したい時は、キーの配列を、連想配列とは別に用意する必要があります。

hasheach.pl
$n = 0;
$data{'AAA'} = "xxx"; $keys[$n++] = "AAA";
$data{'BBB'} = "zzz"; $keys[$n++] = "BBB";
$data{'CCC'} = "yyy"; $keys[$n++] = "CCC";

foreach $key (@keys) {
    print "$key = $data{$key}\n";
}

結果は次のようになります。代入した順序通りに表示されます。

AAA = xxx
BBB = zzz
CCC = yyy

■ 連想配列をキーの辞書順に処理する(keys)

◆ キーの辞書順に処理する

keys() は、連想配列のキーのみからなる配列を返します。これをソートして foreach で回すことにより、連想配列をキーの辞書順に処理することができます。

keys.pl
$data{'AAA'} = "xxx";
$data{'BBB'} = "zzz";
$data{'CCC'} = "yyy";

# キーでソートする
foreach $key (sort keys(%data)) {
    print "$key = $data{$key}\n";
}

結果は次のようになります。

AAA = xxx
BBB = zzz
CCC = yyy

■ 連想配列を値の辞書順に処理する(values)

◆ 値の辞書順にソートして処理

values() は、連想配列の値のみからなる配列を返します。これをソートして参照することにより、連想配列を値順に処理することができます。数値としてソートしたい場合は sort { $a <=> $b } values(%data) としてください。

values.pl
$data{'AAA'} = "xxx";
$data{'BBB'} = "zzz";
$data{'CCC'} = "yyy";

# 値でソートする
foreach $value (sort values(%data)) {
    print "$value\n";
}

結果は次のようになります。

xxx
yyy
zzz
◆ 値の辞書順にソートしてキー付きで処理

値からキーを求めることはできないので、上の例では print "$key = $value\n"; のように記述することができません。これを実現するには次のようにします。

hashsort.pl
$data{'AAA'} = "xxx";
$data{'BBB'} = "zzz";
$data{'CCC'} = "yyy";

foreach $key (sort { $data{$a} cmp $data{$b} } keys(%data)) {
    print "$key = $data{$key}\n";
}

これを実行すると次のようになります。

AAA = xxx
CCC = yyy
BBB = zzz

ちょっと複雑ですが、keys(%data) でキーのみの配列を作成し、これを、キーの値で比較しながらソートし、ソートした結果について、foreach で順番に処理します。数値比較の場合は cmp を <=> に変更してください。

■ 連想配列を削除する(delete)

◆ 要素の削除

連想配列の各要素を削除するには、delete を用います。

hashdel.pl
$data{'AAA'} = "aaa";
$data{'BBB'} = "bbb";
$data{'CCC'} = "ccc";

delete($data{'BBB'});          # BBB の要素を削除する

while (($key, $value) = each(%data)) {
    print "$key = $value\n";
}

結果は次のようになります。BBB が削除されているので、AAA と CCC のみが表示されます。

CCC = ccc
AAA = aaa
◆ 連想配列全体の削除

連想配列全体を削除する(未定義状態にする)には、undef を用います。

undef(%data);

■ 多次元連想配列を用いる

◆ 連想配列と配列の多次元

上記のように、連想配列と配列を組み合わせて使用することもできます。

mhash1.pl
$person[0]{'NAME'} = "Tanaka";
$person[0]{'AGE'} = 26;
$person[1]{'NAME'} = "Suzuki";
$person[1]{'AGE'} = 32;

for ($i = 0; $i <= $#person; $i++) {
    foreach $key ('NAME', 'AGE') {
        print "person[$i]{$key} = $person[$i]{$key}\n";
    }
}

結果は次のようになります。

person[0]{NAME} = Tanaka
person[0]{AGE} = 26
person[1]{NAME} = Suzuki
person[1]{AGE} = 32
◆ 連想配列と連想配列の多次元

連想配列と連想配列を多次元に組み合わせることもできます。この場合、each() はひとつめのキーと、そのキーに対応する連想配列への リファレンス を返します。

mhash2.pl
$person{'TANAKA'}{'AGE'} = 26;
$person{'TANAKA'}{'ADDR'} = "東京";
$person{'SUZUKI'}{'AGE'} = 32;
$person{'SUZUKI'}{'ADDR'} = "大阪";

while (($key, $ref) = each(%person)) {
    print "$key / $ref->{'AGE'} / $ref->{'ADDR'}\n";
}

結果は次のようになります。

SUZUKI / 32 / 大阪
TANAKA / 26 / 東京

Copyright (C) 2002 杜甫々