【问题标题】:What is better to use out of in_array() and || operator?in_array() 和 || 中哪个更好用操作员?
【发布时间】:2013-01-28 17:57:17
【问题描述】:

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

假设如果$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 的可能值数量较少时?

【问题讨论】:

  • 您可以编写一个基准脚本。循环函数几百万次,看看什么是最快的......
  • 说“PHP 的数组性能不是很好”就像说“汽车不是很快”。 上下文非常重要。对别人来说快的可能对你来说很慢,反之亦然,实际上它们几乎可以肯定足以满足你的需要。

标签: php arrays performance


【解决方案1】:

Write a benchmark script.

但总的来说,选择哪种变体几乎不应该取决于性能。尤其是在输入数据非常非常小(比如

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

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

Premature optimization is the root of all evil.

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • Warning: array_key_exists() expects parameter 2 to be array 但是,PHP 中的函数调用开销太大。
    • 修正了参数的顺序。 in_array() 具有相同的函数调用开销,我怀疑这将是大量值的​​瓶颈。
    • 而不是调用array_key_exists(),只需访问$test_array[$x]。这不是array_flip() 的全部目的吗?
    • @SparKot 访问该元素将在找不到索引时发出警告。该警告的代价可能抵消了保存的函数调用开销。
    • isset 会比 array_key_exists 快。而且它不会引发“未定义索引”警告。
    【解决方案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() 的包装器,它提供微秒浮点数,$Table 是Console_Table 实例。

    【讨论】:

    • 如果要进行的比较次数大于 50 或者说 100 怎么办?
    • @SparKot in_array 将变得太慢。阅读我回答的第一段。
    • 这个答案完全错误。 “显然 in_array() 会更慢,因为它有额外的函数调用开销。” 不,您的 in_array 案例更慢,因为您每次都声明一个庞大的数组。 array ('a', 'b', ... 'z') 负责您的号码,而不是拨打in_array。你的基准被搞笑打破了,你的结论完全不正确。
    • @meagar 我按照你说的做了基准测试。但结果并没有太大变化。所以看来你在评论中的建议是完全错误的。
    • @meagar 我同意内置函数总是更可取的。但与 PHP 编写的函数相比,它们更可取。在这里,我们将 语言结构 与内置函数进行比较。语言结构总是更快。他们直接编译成 C 语句。并将内置函数编译为 C 函数。
    【解决方案4】:

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

    使用数组时,您可以根据需要动态扩展它。 它还能让你的代码保持干净。

    据我所知,与使用循环手动搜索相比,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" ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-29
      • 1970-01-01
      • 2013-03-09
      • 2013-09-02
      • 2023-03-23
      • 2012-04-11
      • 1970-01-01
      • 2013-01-09
      相关资源
      最近更新 更多