foreach(explode(',' $foo) as $bar) { ... }
对
$test = explode(',' $foo);
foreach($test as $bar) { ... }
在第一个示例中,它是每次迭代的
explode
字符串还是 PHP 将其保存在内存中并在其自己的临时变量中分解?从效率的角度来看,创建额外的变量$foo
有意义还是两者几乎相等?! 我认为可以通过三种主要方法来解决这个问题。
进入循环之前爆炸并赋值
可能由于分配而消耗更多内存
$test
这是三个版本:
1)
<?php
ini_set('memory_limit', '1024M');
$listStr = 'text';
$listStr .= str_repeat(',text', 9999999);
$timeStart = microtime(true);
/*****
* {INSERT LOOP HERE}
*/
$timeEnd = microtime(true);
$timeElapsed = $timeEnd - $timeStart;
printf("Memory used: %s kB\n", memory_get_peak_usage()/1024);
printf("Total time: %s s\n", $timeElapsed);
2)
// explode separately
$arr = explode(',', $listStr);
foreach ($arr as $val) {}
3)
// explode inline-ly
foreach (explode(',', $listStr) as $val) {}
结果
结论
从整体上看,这些方法对于“合理大小”(几百或几千)的列表来说都足够快。
// tokenize
$tok = strtok($listStr, ',');
while ($tok = strtok(',')) {}
explode()
进行函数调用的调用堆栈开销造成的。下面详细介绍这一点。
strtok()
ing 确实领先于标记化。
O(1)与 O(n) 我在图表中添加了一个奖励,我在循环中运行方法 1) 并调用函数。我使用了
explode()
,认为这将是一个相对相似的执行时间。这是有争议的,但我只是想表达一个一般性的观点。 (我只运行了
strlen($val)
并忽略了它的输出。我没有将它分配给任何东西,因为分配会增加额外的时间成本。)
strlen($val)
从结果表中可以看出,它成为三种方法中最慢的。
最后的想法
创建不同变量或其他方式的影响可以忽略不计。 PHP 解释器需要维护一个指向下一项的位置的指针,无论它们是否是用户定义的。
// explode separately
$arr = explode(',', $listStr);
foreach ($arr as $val) {strlen($val);}