【问题标题】:What's quicker and better to determine if an array key exists in PHP?确定 PHP 中是否存在数组键有什么更快更好的方法?
【发布时间】:2010-10-16 13:26:06
【问题描述】:

考虑这两个例子...

$key = 'jim';

// example 1
if (isset($array[$key])) {
    // ...
}

// example 2    
if (array_key_exists($key, $array)) {
    // ...
}

我很想知道这些是否更好。我一直使用第一个,但在这个网站上看到很多人使用第二个示例。

那么,哪个更好?快点?意图更清晰?

【问题讨论】:

  • 我没有运行任何基准测试,没有。我应该先问吗?
  • isset 的行为永远不会与array_key_exists 完全相同,如果密钥不存在,则假定使其行为相同的代码示例会引发通知。
  • in_array 怎么样? maettig.com/1397246220
  • @DanMan, in_arrayO(n) 因为它检查的是值而不是键。除非您的 n 非常小,否则它们几乎总是会变慢。
  • 为什么不$array[$key] === null

标签: php performance


【解决方案1】:

isset() 更快,但与array_key_exists() 不同。

array_key_exists() 纯粹检查键是否存在,即使值是NULL

而 如果键存在且值为NULLisset() 将返回false

【讨论】:

  • 您是否有特定资源声称 isset 更快?
  • @Francesco Pasa 想一想。 isset 不是数组搜索功能,它只检查符号表中是否存在变量,不会遍历数组。另一方面,array_key_exists 将迭代/搜索指定数组的第一维中的键。
  • @Rain 我很确定array_key_exists() 只会检查键是否在数组中,这意味着它不会进行搜索,因为它是一个哈希表。
【解决方案2】:

如果你对我最近做过的一些测试感兴趣:

https://stackoverflow.com/a/21759158/520857

总结:

| Method Name                              | Run time             | Difference
=========================================================================================
| NonExistant::noCheckingTest()            | 0.86004090309143     | +18491.315775911%
| NonExistant::emptyTest()                 | 0.0046701431274414   | +0.95346080503016%
| NonExistant::isnullTest()                | 0.88424181938171     | +19014.461681183%
| NonExistant::issetTest()                 | 0.0046260356903076   | Fastest
| NonExistant::arrayKeyExistsTest()        | 1.9001779556274      | +209.73055713%

【讨论】:

  • 重要提示:arrayKeyExists 计时被发现非常错误——它检查的是值而不是键——点击该链接查看 7.1 中的修订计时,这好多更好. (如果 Populus 重新进行该测试,在早期的 php 版本中也会更好。)
【解决方案3】:

嗯,主要区别在于isset() 不会为对应于空值的数组键返回true,而array_key_exists() 会。

运行small benchmark 表明isset() 更快,但可能并不完全准确。

【讨论】:

  • 你能用更正确的 "(isset($array[$i]) || $array[$i] === null)" 再次运行基准测试吗?
  • 哦,你能发布一个说明这两个变体显示出多少性能差异吗?谢谢!
  • @Tomalak,我运行了您建议的示例,它指出 array_key_exists() 比使用 || 的 isset() 快操作员。 codepad.org/5qyvS93x
  • 起死回生...但我也重新运行了基准测试,并进行了调整,因此第二个 for 循环必须初始化它自己的计数器并清除结果数组。它显示“isset || null”更快。 codepad.org/Np6oPvgS
  • @Tomalak, isset($array[$i]) || $array[$i] === null 没有意义,因为它会为每种情况返回 true。无论输入如何,您都不会从isset($array[$i]) || $array[$i] === null 得到错误。
【解决方案4】:

Php 7 提供了使用Null Coalescing Operator 的可能性。

已添加空合并运算符 (??) 作为语法糖,用于需要将三元组与 isset() 结合使用的常见情况。如果存在且不为 NULL,则返回其第一个操作数;否则返回第二个操作数。

所以现在您可以指定一个默认值,以防该值为 null 或该键不存在:

$var = $array[$key] ?? 'default value'

【讨论】:

    【解决方案5】:

    我想在这个问题上加 2 美分,因为我错过了一个中间出路。

    如前所述,isset() 将评估键的值,因此如果该值为 null,它将返回 false,其中 array_key_exists() 只会检查该键是否存在于数组中。


    我使用 PHP 7 运行了一个简单的基准测试,显示的结果是完成迭代所花费的时间:

    $a = [null, true];
    
    isset($a[0])                            # 0.3258841  - false
    isset($a[1])                            # 0.28261614 - true
    isset($a[2])                            # 0.26198816 - false
    
    array_key_exists(0, $a)                 # 0.46202087 - true
    array_key_exists(1, $a)                 # 0.43063688 - true
    array_key_exists(2, $a)                 # 0.37593913 - false
    
    isset($a[0]) || array_key_exists(0, $a) # 0.66342998 - true
    isset($a[1]) || array_key_exists(1, $a) # 0.28389215 - true
    isset($a[2]) || array_key_exists(2, $a) # 0.55677581 - false
    
    array_key_isset(0, $a)                  # 1.17933798 - true
    array_key_isset(1, $a)                  # 0.70253706 - true
    array_key_isset(2, $a)                  # 1.01110005 - false
    

    我已将此自定义函数的结果与此基准一起添加以完成:

    function array_key_isset($k, $a){
        return isset($a[$k]) || array_key_exists($k, $a);
    }
    

    如前所述,isset() 是最快的方法,但如果值为 null,它可能返回 false。这可能会产生不需要的结果,如果是这种情况,通常应该使用array_key_exists()

    但是有一个中间出路,那就是使用isset() || array_key_exists()。此代码一般使用更快的函数isset()if isset() 返回false 使用array_key_exists() 进行验证。如上表所示,它与直接调用isset() 一样快。

    是的,编写起来有点多,将其包装在一个函数中虽然速度较慢,但​​也容易得多。如果您需要它来提高性能、检查大数据等,请将其完整地写出来,否则如果它是 1 次使用,那么函数 array_key_isset() 中非常小的开销可以忽略不计。

    【讨论】:

      【解决方案6】:

      php.net 有所不同,您将阅读:

      isset() 不为数组返回 TRUE 对应于 NULL 值的键, 而 array_key_exists() 可以。

      一个非常非正式的测试显示 array_key_exists()isset() 慢大约 2.5 倍

      【讨论】:

        【解决方案7】:

        结合 isset()is_null() 可以在其他函数中获得最佳性能,例如:array_key_exists()isset()isset() + array_key_exists()is_null()isset() + is_null(),唯一的这里的问题是,如果键不存在,该函数不仅会返回 false,而且即使键存在并且具有空值。

        基准脚本:

        <?php
          $a = array('a' => 4, 'e' => null)
        
          $s = microtime(true); 
          for($i=0; $i<=100000; $i++) { 
            $t = (isset($a['a'])) && (is_null($a['a'])); //true 
            $t = (isset($a['f'])) && (is_null($a['f'])); //false
            $t = (isset($a['e'])) && (is_null($a['e']));; //false 
          } 
        
          $e = microtime(true); 
          echo 'isset() + is_null() : ' , ($e-$s)."<br><br>";
        ?>
        

        学分https://web.archive.org/web/20140222232248/zomeoff.com/php-fast-way-to-determine-a-key-elements-existance-in-an-array/

        【讨论】:

          【解决方案8】:

          至于“更快”:试试看(我的钱在array_key_exists(),但我现在不能尝试)。

          至于“更清晰的意图”:array_key_exists()

          【讨论】:

          【解决方案9】:

          显然第二个例子的意图更清楚,这是毫无疑问的。要弄清楚示例 #1 的作用,您需要熟悉 PHP 的变量初始化特性 - 然后您会发现它对 null 值的作用不同,等等。

          至于哪个更快 - 我不打算推​​测 - 在你的 PHP 版本上以紧密的循环运行几十万次,你会发现:)

          【讨论】:

            【解决方案10】:

            我想补充一点,您还可以使用 isset 搜索具有唯一元素的数组。它比使用 in_array、array_search 或 array_key_exists 快得多。您可以使用 array_flip 翻转数组并使用 isset 检查数组中是否存在值。

            <?php
            
            $numbers = [];
            for ($i = 0; $i < 1000000; $i++) {
                $numbers[] = random_int("9000000000", "9999999999");
            }
            
            function evaluatePerformance($name, $callback)
            {
                global $numbers;
                $timeStart = microtime(true);
            
                $result = $callback("1234567890", $numbers) ? 'true' : 'false';
            
                $timeEnd = microtime(true);
                $executionTime =  number_format($timeEnd - $timeStart, 9);
            
                echo  "{$name} result is {$result} and it took {$executionTime} seconds. <br>";
            }
            
            // Took 0.038895845 seconds.
            evaluatePerformance("in_array", function ($needle, $haystack) {
                return in_array($needle, $haystack);
            });
            
            // Took 0.035454988 seconds.
            evaluatePerformance("array_search", function ($needle, $haystack) {
                return array_search($needle, $haystack);
            });
            
            $numbers = array_flip($numbers);
            
            // Took 0.000024080 seconds.
            evaluatePerformance("array_key_exists", function ($needle, $haystack) {
                return array_key_exists($needle, $haystack);
            });
            
            // Took 0.000013113 seconds.
            evaluatePerformance("isset", function ($needle, $haystack) {
                return isset($haystack[$needle]);
            });
            

            【讨论】:

              【解决方案11】:

              您的代码isset($array[$i]) || $array[$i] === null 在任何情况下都将返回 true,即使该键不存在(并产生未定义的索引通知)。为了获得最佳性能,您想要的是if (isset($array[$key]) || array_key_exists($key,$array)){doWhatIWant();}

              【讨论】:

              • $array[$i] === null 将被执行的唯一时间是 $i 存在于数组中并且值为 NULL..
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-10-23
              • 2016-09-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多