执行以下操作是否更快:

 if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') { ... }

或者:

 if (!in_array($var, array('test1', 'test2', 'test3', 'test4') { ... }

是否存在多个值,此时执行其中一个或另一个更快?

(在这种情况下,第二个选项中使用的数组不存在。)

有帮助吗?

解决方案

我强烈建议只使用in_array(),任何速度差可以忽略不计,但分别检测每个变量的可读性是可怕的。

只是为了好玩这是一个测试,我跑:

$array = array('test1', 'test2', 'test3', 'test4');
$var = 'test';
$iterations = 1000000;

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {}
}
$end = microtime(true);

print "Time1: ". ($end - $start)."<br />";

$start2 = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!in_array($var, $array) ) {}
}
$end2 = microtime(true);

print "Time2: ".($end2 - $start2)."<br />";

// Time1: 1.12536692619
// Time2: 1.57462596893

略琐碎音符来监视,如果$var没有设置,方法1需要更长的时间(这取决于有多少条件,你测试)

其他提示

请注意,如果你正在寻找替换一堆!==语句中,你应该通过第三个参数的 in_array true,其强制类型检查在阵列中的项目。

普通!=不需要此,很明显。

在第一会更快 - 第二有很多开销:创建阵列,调用一个函数,搜索数组...

然而,正如我在一个问题说了几个答案了,过早的优化是所有罪恶的根源。你应该写你的代码是可读的,然后的如果的需要进行优化配置文件,然后进行优化。

编辑:

我的定时与@欧文的代码(PHP 5.2.6 /视窗):

Time1: 1.33601498604
Time2: 4.9349629879

移动循环内的阵列(...),作为在这样的问题:

Time1: 1.34736609459
Time2: 6.29464697838

in_array会更快对于大量项目。 “大”的基础上有很多相关的数据和计算机因素都非常主观。既然你问,我想你不处理项目的琐碎数。对于较长的列表,谨慎此信息的,和测量与翻转阵列性能,使得PHP可以利用哈希查找,而不是线性搜索。对于一个“静态”阵列调整可能不会提高性能,但它也可以。

使用欧文的测试代码,用翻转阵列和多个迭代更一致的结果:

$array2 = array_flip($array);
$iterations = 10000000;

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!isset($array2[$var])) {}
}
$end = microtime(true);
print "Time3: ".($end - $start)."<br />";

Time1: 12.875
Time2: 13.7037701607
Time3: 3.70514011383

您好我只是把这种情况下的极端,并指出,随着值的数量平原比较的不可以最高效的方式。

下面是我的代码:

$var = 'test';
$num_values = 1000;
$iterations = 1000000;
print "\nComparison performance test with ".$num_values." values and ".$iterations." loop iterations";
print "\n";

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if ($var != 'test0' &&
        $var != 'test1' &&
        // ...
        // yes I really have 1000 lines in my file
        // ...
        $var != 'test999') {}
}
print "\nCase 1: plain comparison";
print "\nTime 1: ". (microtime(true) - $start);
print "\n";

$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
    $array1[] = 'test'.$i;
}
for($i = 0; $i < $iterations; ++$i) {
    if (!in_array($var, $array1) ) {}
}
print "\nCase 2: in_array comparison";
print "\nTime 2: ".(microtime(true) - $start);
print "\n";

$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
    $array2['test'.$i] = 1;
}
for($i = 0; $i < $iterations; ++$i) {
    if (!isset($array2[$var])) {}
}
print "\nCase 3: values as keys, isset comparison";
print "\nTime 3: ".(microtime(true) - $start);
print "\n";

$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
    $array3['test'.$i] = 1;
}
for($i = 0; $i < $iterations; ++$i) {
    if (!array_key_exists($var, $array3)) {}
}
print "\nCase 4: values as keys, array_key_exists comparison";
print "\nTime 4: ".(microtime(true) - $start);
print "\n";

我的结果(PHP 5.5.9):

Case 1: plain comparison
Time 1: 31.616894006729

Case 2: in_array comparison
Time 2: 23.226133823395

Case 3: values as keys, isset comparison
Time 3: 0.050863981246948

Case 4: values as keys, array_key_exists comparison
Time 4: 0.13700890541077

我同意,那是一个有点极端,但它显示的大局,在PHP中的哈希表类关联数组的巨大潜力,你只需要使用它

请注意,作为RoBorg指出的那样,在建立该阵列,所以应该在迭代循环内移动的开销。出于这个原因,SPARR的帖子也有点误导,因为与array_flip函数的开销。

下面是与所有5个变化另一示例:

$array = array('test1', 'test2', 'test3', 'test4');
$var = 'test';
$iterations = 1000000;

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
   if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {}
}
print "Time1: ". (microtime(true) - $start);

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
   if (!in_array($var, $array) ) {}
}
print "Time2: ".(microtime(true) - $start);

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
   if (!in_array($var, array('test1', 'test2', 'test3', 'test4')) ) {}
}
print "Time2a: ".(microtime(true) - $start);

$array2 = array_flip($array);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
  if (!isset($array2[$var])) {}
}
print "Time3: ".(microtime(true) - $start);

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    $array2 = array_flip($array);
  if (!isset($array2[$var])) {}
}
print "Time3a: ".(microtime(true) - $start);

我的结果:

Time1 : 0.59490108493 // straight comparison
Time2 : 0.83790588378 // array() outside loop - not accurate
Time2a: 2.16737604141 // array() inside loop
Time3 : 0.16908097267 // array_flip outside loop - not accurate
Time3a: 1.57209014893 // array_flip inside loop

总之,使用array_flip(与isset)比inarray快,但速度不如直比较。

当谈到 PHP 时,并询问是否:

  • 一组“if”和“else if”,
  • 带有一组“或”条件的“if”(如原始帖子详细信息中所示),或
  • 将“in_array”与动态构造的数组一起使用,

更好,

人们应该记住,PHP 语言的“switch”语句是针对这种情况设计的一种替代方案,并且可能是一个更好的答案。(虽然发帖者的示例引导我们仅比较两个解决方案,但实际的问题标题要求考虑 in_array 与 PHP 语句,所以我认为这是公平的游戏)。

那么,在海报的示例中,我建议:

switch ($var)
{ case 'test1': case 'test2': case 'test3': case 'test4':
     echo "We have a good value"; break;
  default:
     echo "We do not have a good value";
}

我希望 PHP 允许在这种情况下使用一些非原始结构,例如表示“or”的逗号。但以上是 PHP 设计者认为的最清晰的处理方式。而且它在执行时似乎也比其他两种替代方案更高效。

只要我谈论的是愿望清单,在 SQL 中找到的“IN”对于发帖者的示例情况会更加清晰。

这种想法可能导致人们在这种情况下想要使用“in_array”,但不幸的是,必须构建一个数据结构,然后使用为该数据结构设计的谓词,而不是有一种方法说出来就不会发生这种开销。

这是这个长凳与另一个案例的实时更新 https://3v4l.org/OA2S7

PHP 7.3 的结果:

  • 多重比较: 0.057507991790771

  • 数组中: 0.02568507194519

  • array_flip() 外循环测量+ isset(): 0.014678001403809

  • array_flip() 外部循环未测量 + isset(): 0.015650033950806

  • foreach 和比较: 0.062782049179077

我测试

$array = array('test1', 'test2', 'test3', 'test4');
$var = 'test';
$iterations = 1000000;

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {}
}
$end = microtime(true);

print "Time1: ". ($end - $start)."<br />";

$start2 = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!in_array($var, $array) ) {}
}
$end2 = microtime(true);

print "Time2: ".($end2 - $start2)."<br />";

$array_flip = array_flip($array);

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!isset($array_flip[$var])) {}
}
$end = microtime(true);
print "Time3: ".($end - $start)."<br />";

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!isset($array[$var])) {}
}
$end = microtime(true);

print "Time4: ". ($end - $start)."<br />";
  

时间1:0.20001101493835

     

时间2:0.32601881027222

     

时间3:0.072004079818726

     

时间4:0.070003986358643

scroll top