仕事中にPHPの配列の挙動について聞かれました。「どうだったかな」と思い出してみると、PHPの配列は少し変わった動きなので、改めてちゃんと理解しておきます。
PHPには、添字配列がない
タイトルには「純粋な配列」と書きましたが、普通に「配列」というと、添字が0から順に連番で並んでいて、それぞれに対応する値が入っているものを指します。
PHPのオンラインマニュアルを見てみます。
PHP においては添字配列と連想配列の間に違いはなく、配列型は 1 つだけで、 同じ配列で整数のインデックスと文字列のインデックスを同時に使えます。
ここでは連想配列と区別するために「添字配列」という言葉が使われていますが、PHPには「純粋な配列」がないと書かれています。
純粋な配列を定義できるような・・・
PHPで、普通の配列を定義するというと、以下のようなコードになると思います。
$array = array( 'zero', 'one', 'two', ); |
print_r関数で表示させてみます。
Array ( [0] => zero [1] => one [2] => two ) |
これは、先に書いたように「添字が0から順に連番で並んでいて、それぞれに対応する値が入っているもの」なので、一見「純粋な配列」ですよね。
というか、普通の人はそのつもりで定義していますよね。
添字が連番であることが保証されていない
これが純粋な配列ではないことは、以下のコードで分かります。
$array[100] = 'hundred'; |
先ほどの配列に、添字100の値としてhundredという文字列を代入して、これを表示してみます。
Array ( [0] => zero [1] => one [2] => two [100] => hundred ) |
すると、「添字が0から順に連番で並んでいる」という条件があっけなく崩れました。
途中の要素を消しても詰められない。
先ほどの配列から逆に、既に存在している要素を削除してみます。
unset($array[1]); |
この結果の配列は次のようになります。
Array ( [0] => zero [2] => two ) |
これの場合、添字2だった要素が前に詰められるかと思いきや、単に添字1が存在しなくなって連番ではなくなります。
PHPの配列は、順序付き連想配列
PHPのオンラインマニュアルには次のように書かれています。
PHP の配列は、実際には順番付けられたマップです。
マップというのは連想配列と同じ意味ですが、PHPの配列は連想配列なので添字は数字に限定されませんし、連番でなければいけないという制限もありません。
Javaの連想配列はMap、Objective-Cの連想配列はNSDictionaryなどですが、これらはキーと値の対応だけを持っていて順序が保証されません。キーから値を高速に取り出すことに最適化された配置がされるので、どんな順序で取り出されるか分かりません。
PHPの場合は少し特殊で、連想配列が「純粋な配列」の機能も兼ねる必要があるため、順序をもっています。つまり、最後に追加した値は最後に取り出されます。
という感じで、PHPには連想配列しかないということを理解すれば、少しは配列の扱いが楽になるのではないでしょうか。