phpの連想配列でキーの存在を確認する

php

phpで連想配列のキーが存在するかを確認する方法ですが、やり方によってはwarningが出力されたりと、何も考えずに使うとやっかいなこともあります。

今回は、速度面も含め自分が日ごろから利用する方法を紹介します。

キーの存在を確認する方法

phpで下記のような連想配列を扱う場合に、キーが存在するかを見る場合に、この様に記述しているものを見かけます。

Example – 1

<?php

$ary = [
    'a' => 1, 
    'b' => 2,
    'c' => 3
];

if (isset($ary['a'])) {
    echo $ary['a'];
}

この様な場合は、特に問題はなく動きますが、下記のような場合にはwarningが発生します。

Example – 2

<?php

$ary = [
    'a' => 1, 
    'b' => 2,
    'c' => 3
];

if (isset($ary['d'])) {
    echo $ary['d'];
}

上記の2つの例についての違いは、配列($ary)にキーが存在している、存在しないの違いとなります。
※ただし、Example – 2の場合には実行した際に、warningが発生してしまいます。

決められた連想配列の場合には、キーの存在を気にしなくていいので、Example – 1の様な記述で問題ありませんが、Example – 2の様にキーが存在しない場合を考える必要がある場合には、この記述では問題があります。

では、どのようにするのがいいか?と言う正解を下記に記述します。

確実な方法

<?php

$ary = [
    'a' => 1, 
    'b' => 2,
    'c' => 3
];

if (array_key_exists('a', $ary)) {
    echo $ary['a'];
}

if (array_key_exists('d', $ary)) {
    echo $ary['d'];
}

issetではなく、array_key_existsを利用することでwarningも出さずに連想配列のキーが存在しているかを確認することができます。

では、速度面での違いはあるのか?と言う点も確認しておきましょう。

パターン1:キーが存在する連想配列の場合

コード

<?php

$ary = [
    'a' => 1, 
    'b' => 2,
    'c' => 3
];

$start = 0;
$marge = 0;

for ($i = 0; $i < 10; $i++) {
    $start = measure();
    if (isset($ary['a'])) { }
    $marge += measure() - $start;
}
echo ($marge / 10).PHP_EOL;

$start = 0;
$marge = 0;

for ($i = 0; $i < 10; $i++) {
    $start = measure();
    if (array_key_exists('a', $ary)) { }
    $marge += measure() - $start;
}
echo ($marge / 10).PHP_EOL;

function measure() {
    list($usec, $sec) = explode(' ', microtime());
    return ((float)$usec + (float)$sec);
}

実行結果

# 実行1回目
1.1277198791504E-5
6.2704086303711E-6
# 実行2回目
6.6041946411133E-6
3.0517578125E-6
# 実行3回目
1.2421607971191E-5
6.2942504882812E-6
# 実行4回目
1.1610984802246E-5
2.3174285888672E-5
# 実行5回目
1.0013580322266E-5
4.9591064453125E-6

パターン2:キーが存在しない連想配列の場合

コード

<?php

$ary = [
    'a' => 1, 
    'b' => 2,
    'c' => 3
];

$start = 0;
$marge = 0;

for ($i = 0; $i < 10; $i++) {
    $start = measure();
    if (isset($ary['d'])) { }
    $marge += measure() - $start;
}
echo ($marge / 10).PHP_EOL;

$start = 0;
$marge = 0;

for ($i = 0; $i < 10; $i++) {
    $start = measure();
    if (array_key_exists('d', $ary)) { }
    $marge += measure() - $start;
}
echo ($marge / 10).PHP_EOL;

function measure() {
    list($usec, $sec) = explode(' ', microtime());
    return ((float)$usec + (float)$sec);
}

実行結果

# 実行1回目
1.218318939209E-5
6.3180923461914E-6
# 実行2回目
1.3494491577148E-5
6.2942504882812E-6
# 実行3回目
1.1587142944336E-5
6.2942504882812E-6
# 実行4回目
1.4185905456543E-5
6.2227249145508E-6
# 実行5回目
1.2993812561035E-5
8.392333984375E-6

検証した感想

キーが存在しない場合の速度が明らかに違うのがわかります。
※検証の方法が正しいかは微妙ですが・・・。

これらのことを踏まえ、キーが絶対に存在する場合にはisset、キーが存在するか不明な場合にはarray_key_existsでチェックするのが最良の方法ではないかと思われます。

コメント

  1. ytaro より:

    >>では、どのようにするのがいいか?と言う正解を下記に記述します。
    の箇所が
    if (array_key_exists($ary[‘a’]))
    となってますが、
    if (array_key_exists(‘a’,$ary))
    の誤りではないでしょうか。

  2. errorcode より:

    ご指摘頂きありがとうございます!
    こちら記載内容を修正させて頂きましたm(_ _m)

タイトルとURLをコピーしました