マップ

目次
  • 解説
  • 1. 学習の準備
  • 2. マップとは
  • 3. マップと要素数・ループ
  • 4. マップの操作
進捗を変更する




解説

1. 学習の準備


下表のとおり学習用のクラスを作成して、その中にmainメソッドを作っておきましょう。

ファイル名AssociativeArray.php
クラス名AssociativeArray

2. マップとは


配列に使用してきた添字は、先頭から何番目の要素であるかを示すただの番号でした。要素を特定する際に文字列を使用できる仕組みがマップです。

一般的に、配列では添字をIndexと表現しますが、マップではKeyと表現します。また、この「KeyValue(要素の値)」を紐づけて管理する配列を「連想配列」と呼びます。

配列のページで見たケーキ販売数カウント処理の例では、バラバラの変数を配列化したことで処理が簡潔に書けるようになりましたね。しかし、ケーキを特定する情報が番号になってしまったことで、どのケーキが何番なのかという情報を別途管理する必要ができてしまいました。

マップを利用すれば、ケーキの名前をそのままキーとして使用できるため、処理の簡潔さとデータの扱いやすさを両立できるのです。

今まで配列として利用してきましたが、実はPHPの配列は他のプログラミング言語でいうところの配列のように利用できるだけでありその正体はマップです。

// Keyがstring型でValueがint型の連想配列でカウンターを作成
$sellCounter = [];

// 売れたケーキの情報をレジなどから随時受け取る何らかの処理
// cakeNameがケーキの名前、sellCountが売れた数とする
~~~

// 情報を受け取る度に販売数を加算する処理
$sellCounter[cakeName] = ($sellCounter[$cakeName] ?? 0) + $sellCount;

次のサンプルコードを作成して、マップの動きを確認してみましょう。
ブラウザから「http://localhost/php_basic/AssociativeArray.php」を確認してください。

    static function practiceMap() {
        $map = [];                           // 作成
        $map['dog'] = 'いぬ';                // 要素追加
        $map['cat'] = 'ねこ';                // 要素追加
        Logger::echo($map['cat']);           // 参照
        $map['cat'] = '猫';                  // 参照内容変更
        Logger::echo($map['cat']);           // 参照
        $map['chicken'] = 'にわとり';        // 要素追加
        Logger::echo($map['chicken']);      // 参照
        unset($map['dog']);                 // 要素削除
        Logger::echo(get_debug_type($map['dog'])); // 削除済みでもエラーではなく NULL
        Logger::echo(get_debug_type($map['cow'])); // 元々存在しなくても NULL
    }
[2020/12/31 12:34:56] ねこ
[2020/12/31 12:34:56] 猫
[2020/12/31 12:34:56] にわとり
[2020/12/31 12:34:56] null
[2020/12/31 12:34:56] null

3. マップと要素数・ループ


PHPの配列は配列としてもマップとしても利用できますが、マップとして利用する際は添字が0から始まり要素数 - 1までという特徴を持っていないため、for文ではなく、foreachで値を取得します。

    static function practiceMapLoop() {
        $map = [];
        $map['いぬ'] = 'わん!';
        $map['ねこ'] = 'にゃん!';
        $map['にわとり'] = 'こけこっこー!';

        foreach ($map as $mapValue) { // Valueだけを列挙
            Logger::echo($mapValue);
        }
    }

また、foreachブロック内でValueだけでなくKeyも必要な場合は以下のようにします。

    static function practiceMapLoop() {
        $map = [];
        $map['いぬ'] = 'わん!';
        $map['ねこ'] = 'にゃん!';
        $map['にわとり'] = 'こけこっこー!';

        foreach ($map as $mapKey => $mapValue) { // KeyとValueを列挙
            Logger::echo($mapKey . ' => ' . $mapValue);
        }
    }

4. マップの操作


配列では添字を使って各要素を指定して代入や参照をおこない、countメソッドを使用して要素の数を取得しましたね。マップには他にも便利なメソッドが用意されていて次のような操作がおこなえます。

  • 削除:unsetメソッド
  • 並び替え:〜sortメソッド
  • 値が含まれているか:in_arrayメソッド
  • キーが含まれているか:array_key_existsメソッド

削除:unsetメソッド

unsedメソッドでは、丸括弧に入れる値(以下、引数と呼びます)にKeyを指定することで、そのKeyとValueの組み合わせを配列から削除します。

    static function practiceMapUnset() {
        $map = [];
        $map['dog'] = 'いぬ';
        $map['cat'] = 'ねこ';
        unset($map['dog']);                        // 削除
        Logger::echo(get_debug_type($map['dog']));
        Logger::echo($map['cat']);
    }
[2020/12/31 12:34:56] null
[2020/12/31 12:34:56] ねこ

また、keyを指定しないことですべての要素を削除することができます。

    static function practiceMapUnset() {
        $map = [];
        $map['dog'] = 'いぬ';
        $map['cat'] = 'ねこ';
        unset($map);                               // 削除
        Logger::echo(get_debug_type($map['dog']));
        Logger::echo(get_debug_type($map['cat']));
    }

並び替え:〜sortメソッド

ksortメソッドを使用することでKeyを昇順でソートすることができ、krsortメソッドを使用することでKeyを降順でソートすることができます。

    static function practiceMapSort() {
        $map = [];
        $map['01'] = 'bbb';
        $map['02'] = 'ccc';
        $map['03'] = 'aaa';
        krsort($map);                                 // Keyの降順
        foreach ($map as $mapKey => $mapValue) {
            Logger::echo($mapKey . '=>' . $mapValue);
        }
        ksort($map);                                  // Keyの昇順
        foreach ($map as $mapKey => $mapValue) {
            Logger::echo($mapKey . '=>' . $mapValue);
        }
    }
[2020/12/31 12:34:56] 03=>aaa
[2020/12/31 12:34:56] 02=>ccc
[2020/12/31 12:34:56] 01=>bbb
[2020/12/31 12:34:56] 01=>bbb
[2020/12/31 12:34:56] 02=>ccc
[2020/12/31 12:34:56] 03=>aaa

またasort・arsortメソッドを使用することでKeyではなくValueでソートすることができます。

    static function practiceMapSort() {
        $map = [];
        $map['01'] = 'bbb';
        $map['02'] = 'ccc';
        $map['03'] = 'aaa';
        arsort($map);                                 // Valueの降順
        foreach ($map as $mapKey => $mapValue) {
            Logger::echo($mapKey . '=>' . $mapValue);
        }
        asort($map);                                  // Valueの昇順
        foreach ($map as $mapKey => $mapValue) {
            Logger::echo($mapKey . '=>' . $mapValue);
        }
    }
[2020/12/31 12:34:56] 02=>ccc
[2020/12/31 12:34:56] 01=>bbb
[2020/12/31 12:34:56] 03=>aaa
[2020/12/31 12:34:56] 03=>aaa
[2020/12/31 12:34:56] 01=>bbb
[2020/12/31 12:34:56] 02=>ccc

値が含まれているか:in_arrayメソッド

in_arrayメソッドでは、Valueを比較して、一致するValueが見つかった場合はtrueを、見つからなかった場合はfalseを返します。

    static function practiceMapInArray() {
        $map = [];
        $map['ショート'] = 5;
        $map['チーズ'] = 10;
        $map['チョコ'] = 0;
        if (!in_array(0, $map)) {
            Logger::echo('全ての商品が販売中です');     // Valueがなければ
        } else {
            Logger::echo('一部の商品が売り切れています'); // Valueがあれが
        }
    }
[2020/12/31 12:34:56] 一部の商品が売り切れています

キーが含まれているか:array_key_existsメソッド

array_key_existsメソッドでは、Keyを比較して、一致するKeyが見つかった場合はtrueを、見つからなかった場合はfalseを返します。

    static function practiceMapArrayKeyExists() {
        $map = [];
        $map['ショート'] = 20;
        $map['チーズ'] = 30;
        $map['チョコ'] = 0;
        if (!array_key_exists('チョコ', $map)) {
            $map['チョコ'] = 40;         // Keyがなければ
        } else {
            $map['チョコ'] += 50;        // Keyがあれば
        }
        foreach ($map as $mapKey => $mapValue) {
            Logger::echo($mapKey . ':' . $mapValue);
        }
    }
[2020/12/31 12:34:56] ショート:20
[2020/12/31 12:34:56] チーズ:30
[2020/12/31 12:34:56] チョコ:50