【问题标题】:for vs foreach vs while which is faster for iterating through arrays in phpfor vs foreach vs while 哪个在 php 中遍历数组更快
【发布时间】:2010-12-23 13:27:22
【问题描述】:

在 php 中遍历数组的速度最快的是哪一个?或者是否存在另一个对于遍历数组也更快的方法?

【问题讨论】:

    标签: php arrays for-loop while-loop foreach


    【解决方案1】:

    即使有任何不同,那差异也会很小,根本不重要。

    如果你有一个对数据库的查询,与循环迭代结果相比,这将花费很长时间,以至于for vs foreach vs while 的永恒争论不会改变任何事情-- 至少如果你有合理数量的数据。

    所以,使用:

    • 随你喜欢
    • 任何符合您的编程标准的东西
    • 最适合您的代码/应用程序的方法

    在考虑这种微优化之前,您可以/应该优化许多其他事情。


    如果你真的想要一些数字(即使只是为了好玩),你可以做一些基准测试并在实践中查看结果。

    【讨论】:

    • 什么..?^^ 我不知道带有ASP的winserver比unix系统快...
    • 在遍历大量数据集时,数组会成为相当大的负担。假设您将递归地遍历一大堆数组:PHP 会将每个数组作为新数组复制到其内存中,因此内存使用量可能会呈指数级增长。当您要遍历具有超过 100.000 个重填充嵌套数组的数组时,可能会发生这种情况。
    【解决方案2】:

    进行基准测试。

    没有重大的“性能”差异,因为差异位于逻辑内部。

    • 您使用 foreach 进行数组迭代, 没有整数作为键。
    • 您使用 for 进行数组迭代 整数作为键。

    【讨论】:

      【解决方案3】:

      正确使用,while 是最快的,因为它每次迭代只能进行一次检查,将一个 $i 与另一个 $max 变量进行比较,并且在循环之前(设置 $max 除外)或循环期间($ 除外)没有额外的调用i++; 本质上是在任何循环语句中完成的)。

      当你开始滥用它时(比如 while(list..) ),你当然最好使用 foreach,因为每个函数调用都不会像 foreach 中包含的那样优化(因为它是预先优化的)。

      即便如此,array_keys() 仍为您提供与 foreach 相同的可用性,而且速度更快。 除此之外,如果您喜欢二维数组,自制的 2d_array_keys 将使您能够以更快的方式一直使用 foreach (只需尝试在第一个 foreach 中告诉下一个 foreach,最后一个 foreach 有 作为键 --- )。

      此外,所有与循环的第一项或最后一项相关的问题都使用 while($i

      还有

      while ($people_care_about_optimization!==true){
       echo "there still exists a better way of doing it and there's no reason to use any other one";
      }
      

      【讨论】:

        【解决方案4】:

        对我来说,我根据这个来选择我的循环:

        foreach
        

        在遍历长度未知(或可能未知)的数组时使用。

        for
        

        在遍历已设置长度的数组时使用,或者在需要计数器时使用。

        while
        

        当您以查找或触发某个标志为明确目的而遍历数组时使用。

        现在确实如此,您可以使用类似 FOREACH 循环的 FOR 循环,通过使用 count($array)... 所以最终归结为您的个人偏好/风格。

        【讨论】:

        • 你也可以通过使用类似 foreach($array as $key => $value){ //code here } 来为你的 foreach 添加一个计数
        • while 循环对于使用关联键数组(如果删除数组中的元素则为非连续键)的复杂算法也很有用,并且您需要将当前值与前一个值进行比较/下一个值。您可以使用foreach 循环将前一个值复制到变量中,但您不能使用prev()next() 函数,因为foreach 循环不保留对内部数组指针的引用。
        【解决方案5】:

        一般来说,这三个函数之间没有适用的速度差异。

        提供基准测试结果以展示用于迭代 1 to 10,000 中的数组的不同方法的效率。

        不同 PHP 版本的基准测试结果:https://3v4l.org/a3Jn4

        while $i++: 0.00077605247497559 sec
        for $i++: 0.00073003768920898 sec
        foreach: 0.0004420280456543 sec
        while current, next: 0.024288892745972 sec
        while reset, next: 0.012929201126099 sec
        do while next: 0.011449098587036  sec //added after terminal benchmark
        while array_shift: 0.36452603340149 sec
        while array_pop: 0.013902902603149 sec
        

        考虑到countwhilefor 的个人调用

        $values = range(1, 10000);
        $l = count($values);
        $i = 0;
        while($i<$l){
           $i++;
        }
        
        $l = count($values);
        for($i=0;$i<$l;$i++){
        }
        
        foreach($values as $val){
        }
        

        以下使用while 的示例演示了如何在迭代过程中降低使用效率。

        在功能上迭代数组并保持当前位置时; while 的效率大大降低,因为在迭代期间会调用 next()current()

        while($val = current($values)){
            next($values);
        }
        

        如果数组的当前位置不重要,可以在迭代前调用reset()current()

        $value = reset($values);
        while ($value) {
            $value = next($values);
        }
        

        do ... while 是一种可以使用的替代语法,也可以与在迭代之前调用 reset()current() 以及将 next() 调用移动到迭代结束时结合使用。

        $value = current($values);
        do{
        }while($value = next($values));
        

        array_shift 也可以在迭代期间调用,但这会对性能产生很大的负面影响,因为array_shift 每次调用时都会重新索引数组。

        while($values){
           array_shift($values);
        }
        

        或者array_reverse 可以在迭代之前调用,同时调用array_pop。这样可以避免调用array_shift时重新索引的影响。

        $values = array_reverse($values);
        while($values) {
           array_pop($values);
        }
        

        总之,whileforforeach 的速度不应该是问题,而是在它们内部做了什么来保持阵列的定位。

        在 PHP 5.6.20 x64 NTS CLI 上运行的终端测试:

        【讨论】:

          【解决方案6】:

          请记住,将大量 mysqli_result 预取到一个舒适的数组中可能会引发这样一个问题:使用 for/foreach/while 循环该数组是否更好,但这是一个错误的问题浪费大量内存的解决方案。

          所以不喜欢这个:

          function funny_query_results($query) {
              $results = $GLOBALS['mysqli']->query($query);
              $rows = [];
              while( $row = $results->fetch_object() ) {
                  $rows[] = $results;
              }
              return $rows;
          }
          
          $rows = funny_query_results("SELECT ...");
          foreach($rows as $row) { // Uh... What should I use? foreach VS for VS while?
              echo $row->something;
          }
          

          在一个简单的while 中逐一获取每个mysql_result 的直接方法更加优化:

          $results = $mysqli->query("SELECT ...");
          while( $row = $results->fetch_object() ) {
              echo $row->something;
          }
          

          【讨论】:

            猜你喜欢
            • 2012-10-02
            • 2012-06-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-20
            • 2020-08-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多