for vs foreach vs while 哪个在 php 中遍历数组更快

Posted

技术标签:

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

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

【问题讨论】:

【参考方案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;

【讨论】:

以上是关于for vs foreach vs while 哪个在 php 中遍历数组更快的主要内容,如果未能解决你的问题,请参考以下文章

.map() vs .forEach() vs for() 如何选择?

JavaScript ??? 4 ???????????????????????? for VS forEach() VS for/in VS for/of

JavaScript - For loop vs forEach

for-in vs Object.keys forEach 没有继承属性

Java: for(;;) vs. while(true)

VS快捷键