PHPで配列がシンプルなリストか連想配列かを調べる方法

こんにちは、さるまりんです。

PHPは二つのタイプの配列を扱えます。

一つは数値のインデックスと値を持つリストです。
こんなのですね。

$arrayOfNums = [0, 4, 11, 25, 38];

これをprint_r()で出力するとこうなります。

Array
(
    [0] => 0
    [1] => 4
    [2] => 11
    [3] => 25
    [4] => 38
)

もう一つのタイプは文字列のキーと値を持つ連想配列です。
こんなのです。

$person = [
    'name'    => 'salumarine',
    'age'     => 'unknown',
    'country' => 'Japan',
];

これもprint_r()で出力してみます。

Array
(
    [name] => salumarine
    [age] => unknown
    [country] => Japan
)

is_array()関数を使って配列かどうかは調べられるのですが、それが上のどちらのタイプか区別することはできません。

さあ、どうしましょう?

それぞれの要素のキーをチェックする

連想配列は数字以外のキーがあります(あるとします)。
なので全てのキーが数字ならばリストと判断してチェックしてみます。

関数にするとこうです。

function is_list_by_numeric_keys($array) {
    foreach ($array as $key => $val) {
        if (!is_numeric($key)) {
            return false;
        }
    }
    return true;
}

使ってみます。

echo "is list? " . (is_list_by_numeric_keys($arrayOfNums) ? "yes" : "no") . "\n";
echo "is list? " . (is_list_by_numeric_keys($person) ? "yes" : "no") . "\n";

出力されたのは

is list? yes
is list? no

一つ目がシンプルなリスト、二つ目はそうではないとなっていますね。

array_values()を使う

array_values()は連想配列の値を全て数値のインデックスの配列にして返します。
シンプルなリストが与えられた場合は、元の配列と同じものになります。
なので、こんな風にチェックできます。

array_values($array) === $array

やってみましょう。

function is_list_by_array_values($array) {
    return array_values($array) === $array;
}

上のような関数にしてそれぞれ配列を渡してみます。

echo "is list? " . (is_list_by_array_values($arrayOfNums) ? "yes" : "no") . "\n";
echo "is list? " . (is_list_by_array_values($person) ? "yes" : "no") . "\n";

結果はこうなります。

is list? yes
is list? no

一つ目はリスト、二つ目はそうではないとなっています。

array_keys()を使う

今度はarray_keys()です。こちらは配列のキーを配列で返します。
これと数値のインデックスを値として持つ配列を比べて同じならリストと判断します。
例えば要素が3つの配列のインデックスであれば[0, 1, 2]です。
これをrange()関数を使って取得します。
range(0, count($array)-1)[0, ..., 配列の長さ-1]の配列が作れます。

関数にするとこうなります。

function is_list_by_array_keys($array) {
    return array_keys($array) === range(0, count($array)-1);
}

使ってみましょう。

echo "is list? " . (is_list_by_array_keys($arrayOfNums) ? "yes" : "no") . "\n";
echo "is list? " . (is_list_by_array_keys($person) ? "yes" : "no") . "\n";

結果です。

is list? yes
is list? no

ここまでと同様ですね。

これ、PHP8.1以降だとarray_is_list()という関数が用意されているみたいですね。
それ以前の環境で実現することもあります。
用意されているものは使って効率よく開発をしていきたいと思います。

読んでくださってありがとうございました。
それではまた!