2

考虑到脚本的性能,我问这个问题。知道 PHP 数组的性能不是很好,我正在徘徊在这种情况下哪种方式最好。

假设 if$x等于 a 或 b 或 c 或 d 我们需要action_a()执行,如果不action_b()执行..

我们可以使用以下||操作符来实现它;

if($x == 'a' || $x == 'b' || $x == 'c' || $x == 'd'){
       action_a();
}else{
       action_b();
}

或者我们可以使用in_array()如下方式实现它;

if(in_array($x,array('a','b','c','d'))){
       action_a();
}else{
       action_b();
}

我想知道的是这两个选项中哪一个会表现良好:

  1. 当可能值的数量$x很高时?

  2. 当可能值的数量$x很少时?

4

4 回答 4

6

编写基准脚本。

但总的来说,选择哪种变体几乎不应该取决于性能。特别是在您的输入数据非常非常小(比如<10)的超级琐碎情况下。

这个最重要的标准始终是可读性。

只有在出现不可否认的性能问题时才开始优化代码。

过早的优化是万恶之源

于 2013-01-28T18:00:16.383 回答
3

对于大量值,我不会使用任何一种方法。我将创建一个关联数组,其键是可能的值,并使用isset()

$test_array = array_flip(array('a', 'b', 'c', 'd', ...));
if (isset($test_array[$x])) ...

这有一次性的 O(n) 创建成本$test_array,然后检查匹配是 O(1)。

于 2013-01-28T18:05:23.127 回答
3

这取决于您使用的 PHP 版本。开会PHP 5.3 in_array()慢一些。但在PHP 5.4 或更高版本in_array()中会更快

仅当您认为条件会随着时间的推移而增长或此条件应该是动态的时,才使用in_array().

我做了一个基准测试。循环您的条件 10,000 次。

结果为PHP 5.3.10

+----------------------------+---------------------------+
| Script/Task name           | Execution time in seconds |
+----------------------------+---------------------------+
| best case in_array()       | 1.746                     |
| best case logical or       | 0.004                     |
| worst case in_array()      | 1.749                     |
| worst case logical or      | 0.016                     |
| in_array_vs_logical_or.php | 3.542                     |
+----------------------------+---------------------------+

的结果PHP 5.4

+----------------------------+---------------------------+
| Script/Task name           | Execution time in seconds |
+----------------------------+---------------------------+
| best case in_array()       | 0.002                     |
| best case logical or       | 0.002                     |
| worst case in_array()      | 0.008                     |
| worst case logical or      | 0.010                     |
| in_array_vs_logical_or.php | 0.024                     |
+----------------------------+---------------------------+

最佳情况: 匹配第一个元素。
最坏情况: 匹配最后一个元素。

这是代码。

$loop=10000;
$cases = array('best case'=> 'a', 'worst case'=> 'z');
foreach($cases as $case => $x){
    $a = utime();
    for($i=0;$i<$loop; $i++){
        $result = ($x == 'a' || $x == 'b' || $x == 'c' || $x == 'd' || $x == 'e' || $x == 'f' || $x == 'g' || $x == 'h' || $x == 'i' || $x == 'j' || $x == 'k' || $x == 'l' || $x == 'm' || $x == 'n' || $x == 'o' || $x == 'p' || $x == 'q' || $x == 'r' || $x == 's' || $x == 't' || $x == 'u' || $x == 'v' || $x == 'w' || $x == 'x' || $x == 'y' || $x == 'z');
    }
    $b = utime();
    $ar = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');
    for($i=0;$i<$loop; $i++){
        $result = in_array($x, $ar);
    }
    $c = utime();

    $Table->addRow(array("$case in_array()", number_format($c-$b, 3)));
    $Table->addRow(array("$case logical or", number_format($b-$a, 3)));
}

这是一个提供微秒浮点数utime()的包装器,是一个实例。microtime()$TableConsole_Table

于 2013-01-28T18:15:11.373 回答
0

您的第一个解决方案在性能方面效果很好,当您之后不需要更改任何内容时,但是代码的可读性变得越来越差,您必须检查的值越多。

使用数组时,您可以根据需要动态扩展它。它还使您的代码保持清洁。

据我所知,与使用循环手动搜索相比,in_array 函数的性能相当低。

此外,您可以声明所谓的“地图”:

$actions = [
  "a" => function(){ action_a() ; },
  "b" => function(){ action_b() ; }
] ;

之后,你这样做:

if (isset($actions[$x])) 
  $action[$x]() ;
else
  do_smth() ;

一个小提示:如果你使用 PHP >=5.4,你可以像这样声明一个新数组:

$array = [1,2,3,4,5] ;
$array[] = "I am a new value to push" ;
于 2013-01-28T18:12:15.187 回答