はじめに
周りのメンバーが、連想配列ではなく通常の配列+ループでデータチェックをしている場面がありました。
そこで、連想配列を使うとどんなふうに楽になるのかを共有したいと思い、本記事を書きました。
本記事で解説すること
本記事では、連想配列の簡単な概要、メリット・デメリット、どのような場面で使うのかを解説していきます。
連想配列とは?
簡潔に言うと、配列のキー(添え字)に数値の代わりに文字列を使える配列のことです。
文字列をキーにできるので、以下のような配列を作成できます。自由に意味のあるキーを指定できる配列、と考えてください。
例
通常の配列
msg[0] = 'ごめんなさい';
msg[1] = 'ありがとう';
msg[2] = 'さよなら';
連想配列
msg['謝罪'] = 'ごめんなさい';
msg['お礼'] = 'ありがとう';
msg['別れ'] = 'さよなら';
連想配列のメリット
1つ目:中身が想像しやすい。
上の例のように、連想配列ならキーにデータの意味を明示することができます。データの関連性を明示でき、プログラムの可読性が上がりますので、複数人での開発の際にソース確認がしやすくなります。
2つ目:キー次第でデータに簡単にアクセスできる。
例えば「5 の倍数を 5 で割った結果」を格納する場合を考えます。
連想配列なら、そのまま 元の数値 である5 の倍数をキーとして作成すれば、元の数値をそのままキーに指定してデータにアクセスできます。
しかし、通常の配列だと0からのキーで配列を作成する必要があるため、元の数値ではキーに指定することはできません。
そのため配列を作成する際は0からの作成になり、アクセスする際も元の数値 → キー への変換が必要で、そのぶん手間が増えます。
例
通常の配列
number[0] = 1;
number[1] = 2;
number[2] = 3;
連想配列
number['5'] = 1;
number['10'] = 2;
number['15'] = 3;
このようにキーの設計を工夫することで、データアクセスがシンプルにできます。
連想配列のデメリット
1つ目:コード量が増える場合がある。
キーが文字列になるため、場合によっては記述量が増えます。
また、連想配列を作成する際も配列のようにシンプルではないので、連想配列自体を作成する際には工夫が必要になります。
2つ目:コーディングミスに気づきづらい。
通常の配列で number[01] は数字のキーではないのでエラーなどになりますが、連想配列では number['01'] のように文字列のキーとして成立してしまいます。そのため存在しないキーでも即エラーにはならず、 null で返すだけの場合があります(言語・設定によっては存在しないキーの使用で警告が出る場合もあります)。
このように文字列キーは誤記に気づきづらく、ミスにつながる可能性があります。
3つ目:メモリ使用量が増加する。
連想配列で配列と同じ数だけのデータを格納する場合と比べると、メモリ消費量が増える傾向があります。
どのような場面で使う?
存在するものを探す/存在しないことを確認する場面で特に有用です。
⇒ 存在するものを探すとき
例えば、以下のデータから check_member に列挙した人名の年齢を member_age から取得するとします。
通常の配列
check_member[0] = 'yamada';
check_member[1] = 'tanaka';
check_member[2] = 'katou';
member_age[0][0] = 'tanaka';
member_age[0][1] = '20';
member_age[1][0] = 'satou';
member_age[1][1] = '30';
member_age[2][0] = 'yamada';
member_age[2][1] = '40';
連想配列
check_member['check_1'] = 'yamada';
check_member['check_2'] = 'tanaka';
check_member['check_3'] = 'katou';
member_age['tanaka'] = '20';
member_age['satou'] = '30';
member_age['yamada'] = '40';
プログラム例(PHP)
- 通常の配列版(2重ループが必要)
<?php
$check_member = ['yamada', 'tanaka', 'katou'];
$member = [
['tanaka', '20'],
['satou', '30'],
['yamada', '40'],
];
$result = [];
foreach ($check_member as $name) {
$age = null;
foreach ($member as list($member_name, $member_age)) {
if ($member_name === $name) {
$age = $member_age;
break;
}
}
// 例: ['yamada', '40'], ['tanaka', '20'] のように格納
$result[] = [$name, $age]; // 見つからなければ [名前, null]
}
// 出力
foreach ($result as list($name, $age)) {
echo $name . ' : ' . ($age ?? '不明') . PHP_EOL;
}
- 連想配列版(1回のループで済む)
<?php
$check_member = [
'check_1' => 'yamada',
'check_2' => 'tanaka',
'check_3' => 'katou',
];
// 配列と違い各要素のデータは1つでOK
$member = [
'tanaka' => '20',
'satou' => '30',
'yamada' => '40',
];
$result = [];
foreach ($check_member as $key => $name) {
// 連想配列ならキーでダイレクトに参照できる
$result[$name] = $member[$name] ?? null;
}
foreach ($result as $name => $age) {
echo $name . ' : ' . ($age ?? '不明') . PHP_EOL;
}
ポイント:通常の配列は2重ループが必要ですが、連想配列なら1回のループ+1回の参照で済みます。このように存在するデータを探す処理に連想配列は向いています。
⇒ 存在しないものを探すとき
次のような処理を考えます。
1. 名前を入れる配列を用意
2. ループ開始
3. 入力
4. 入力が "exit" なら終了
5. 入力が配列内に「ない」ことをチェック
6. ない場合は配列に追加
7. ループ終了
8. 配列内のデータを出力
プログラム例(PHP)
- 通常の配列版(毎回の重複チェックが線形探索)
<?php
$names = [];
while (true) {
// CLI入力想定(Webならフォーム入力に置き換え)
$input = trim(fgets(STDIN));
if ($input === 'exit') {
break;
}
// 配列内に「ない」かどうかを in_array で線形チェック
if (!in_array($input, $names, true)) {
$names[] = $input;
echo "追加: {$input}" . PHP_EOL;
} else {
echo "既に存在します: {$input}" . PHP_EOL;
}
}
print_r($names);
- 連想配列版(キー存在チェックで高速に判定)
<?php
$namesMap = [];
while (true) {
// CLI入力想定(Webならフォーム入力に置き換え)
$input = trim(fgets(STDIN));
if ($input === 'exit') {
break;
}
// 連想配列ならキー存在チェックだけでよい(平均O(1)想定)
if (!isset($namesMap[$input])) {
// キー=名前, 値=true などダミーでOK(後で入力値を使用する場合はキーと同じ内容を設定)
$namesMap[$input] = true;
echo "追加: {$input}" . PHP_EOL;
} else {
echo "既に存在します: {$input}" . PHP_EOL;
}
}
// 通常の配列版と同じ形で出力するため、名前リストをキーから取り出し配列に変換
$names = array_keys($namesMap);
print_r($names);
ポイント:通常の配列だと in_array による毎回の線形探索(O(n)) が発生しますが、連想配列はキーの存在確認(平均O(1)想定) で事足ります。
※通常の配列でもデータ量が少ない場合は、気にするほどの検索速度ではないです。しかし、データ量が億単位などの莫大な量を検索する際は、毎回すべてのデータをチェックをする可能性が有るので、検索速度に影響が出てきます。
このように存在しないことのチェックにも連想配列は向いています。
まとめ
- 連想配列は意味のあるキーでデータを直接参照でき、探索・存在チェックが簡潔になります。
- 一方で、文字列キーの誤記は気づきづらいため、
isset/array_key_existsでの存在確認や、定数・列挙に近いキーの管理を意識すると安全です。 - 連想配列は設計次第で可読性とパフォーマンスの両立が可能な機能になります。