确定PHP中是否存在数组键的更快,更好的方法是什么?


157

考虑这两个例子...

$key = 'jim';

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

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

我有兴趣知道这些方法是否更好。我一直使用第一个示例,但是看到很多人在此站点上使用第二个示例。

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


我没有运行任何基准测试,没有。问之前我应该​​有吗?
alex

4
isset永远不会表现出完全一样的效果array_key_exists,如果该键不存在,则本应使其表现相同的代码示例将引发“ Notice”。
deceze


1
@DanMan,in_arrayO(n)因为它检查值而不是键。除非您n很小,否则它们几乎总是会变慢。
Pacerier,2015年

为什么不$array[$key] === null呢?
Pacerier '17

Answers:


237

isset()速度更快,但与并不相同array_key_exists()

array_key_exists()纯粹检查密钥是否存在,即使该值为NULL

isset()将返回false如果该键存在和价值NULL


5
您是否有特定资源声称isset更快?
Francesco Pasa

@Francesco Pasa稍微考虑一下。isset不是数组搜索功能,它仅检查符号表中变量的存在,并且不会遍历数组。array_key_exists另一方面,将在指定数组的第一维中迭代/搜索键。
下雨

@Rain我很确定array_key_exists()只会检查键是否在数组中,这意味着它是哈希表,因此不会进行搜索。
Francesco Pasa

@FrancescoPasa嗯,PHP文档说的是“搜索密钥”。除此之外,我无法判断对他们的“搜索”是否意味着对我而言完全不同的东西。
下雨

32

如果您对某些测试感兴趣,我最近已经做了:

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版本中也会更好。)
ToolmakerSteve

19

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

运行一个小的基准测试表明isset()它速度更快,但可能并不完全准确。


1
您是否可以使用更正确的“(isset($ array [$ i])|| $ array [$ i] === null)”再次运行基准测试?
Tomalak

哦,您会指出两个变体显示多少性能差异吗?谢谢!
Tomalak

1
@Tomalak,我运行了您建议的示例,该示例指出,使用||,array_key_exists()比isset()更快。操作员。codepad.org/5qyvS93x
亚历克斯

1
从死里复生...但是我还重新运行了基准测试,并进行了调整,因此第二个for循环必须初始化其自己的计数器并清除结果数组。它显示“ isset || null”更快。codepad.org/Np6oPvgS
KyleWpppd 2012年

3
@Tomalak isset($array[$i]) || $array[$i] === null没有意义,因为它会true在每种情况下返回。isset($array[$i]) || $array[$i] === null无论输入什么内容,您都不会 出错。
Pacerier

10

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

如前所述,isset()将评估键的值,因此false如果该值是nullarray_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()这是最快的方法,但如果值为,则可以返回false null。这可能会产生不想要的结果,通常array_key_exists()是这样。

但是,有一个中间的出路,那就是使用isset() || array_key_exists()。该代码通常使用更快的功能isset()如果 isset()返回false,用于array_key_exists()验证。如上表所示,其调用速度与普通调用一样快isset()

是的,编写和将其包装到函数中的过程要慢一些,但要容易得多。如果您需要这样做以提高性能,检查大数据等内容将其全部写出,否则,如果仅使用1次而在功能array_key_isset()上的开销很小,则可以忽略不计。


7

在PHP 7中,可以使用Null合并运算符

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

因此,现在您可以分配一个默认值,以防该值为null或该键不存在:

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

6

php.net的区别在于:

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

一个非常非正式的测试表明array_key_exists(),它的速度比慢2.5倍isset()


3

结合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>";
?>

图片来源http : //www.zomeoff.com/php-fast-way-to-determine-a-key-elements-existance-in-an-array/


1

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

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


3
如果您不关心null行为,则isset()实际上要快得多(请参阅randombenchmarks.com/?p=29)。
马特·坎托

0

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

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


-2

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


1
唯一的一次$array[$i] === null将被执行时$我在数组中存在,并且有NULL值..
尼克拉斯·拉松
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.