while(list($ key,$ value)= each($ array))vs.foreach($ array as $ key => $ value)?

jol*_*olt 36 php arrays foreach loops while-loop

最近我遇到了这个奇怪的问题:

while(list($key, $value) = each($array))
Run Code Online (Sandbox Code Playgroud)

没有列出所有数组值,用...替换它...

foreach($array as $key => $value)
Run Code Online (Sandbox Code Playgroud)

......工作得很好

而且,我现在很好奇......这两者有什么区别?

Joh*_*ica 55

你以前穿过阵列了吗?each()记得它在阵列中的位置,所以如果你不这样做reset(),你可以错过物品.

reset($array);
while(list($key, $value) = each($array))
Run Code Online (Sandbox Code Playgroud)

值得一提的是,这种数组遍历的方法很古老,并且被更惯用的foreach所取代.我不会使用它,除非你特别想要利用它的一次性项目性质.

每个数组(数组和$数组)

返回数组中的当前键和值对并使数组光标前进.

each()执行完毕后,数组游标将保留在数组的下一个元素上,或者如果它到达数组的末尾则超过最后一个元素.你必须使用reset(),如果你想再次遍历数组使用each.

(来源:PHP手册)


irc*_*ell 13

嗯,一个区别是each()只能在数组上工作(只能正常工作). foreach将在任何实现traversable接口的对象上工作(当然包括内置数组类型).

在foreach中可能存在微观优化.基本上,foreach等同于以下内容:

$array->rewind();
while ($array->valid()) {
   $key = $array->key();
   $value = $array->current();
   // Do your code here
   $array->next();
}
Run Code Online (Sandbox Code Playgroud)

each基本上做到以下几点:

$return = $array->valid() ? array($array->key(), $array->current()) : false;
$array->next();
return $return;
Run Code Online (Sandbox Code Playgroud)

所以三条线都是相同的.他们都非常相似.可能会有一些微优化,each不需要担心traversable界面......但这最多只是次要的.但它也可以通过布尔强制转换和检查PHP代码与已foreach编译的C 来抵消...更不用说在你的while/each代码中,你要调用两种语言结构和一个函数,而使用foreach它是单一语言构造...

更不用说foreach哇更容易阅读...更容易阅读,更灵活意味着 - 对我foreach来说- 是明显的赢家.(这并不是说each没有它的用​​途,但我个人从来不需要它)...


Xeo*_*oss 10

警告!Foreach创建数组的副本,因此当foreach迭代,您无法修改.each()仍有一个目的,如果你在循环遍历它的元素和索引时对数组进行实时编辑,那么它可能非常有用.

// Foreach creates a copy
$array = [
  "foo" => ['bar', 'baz'],
  "bar" => ['foo'],
  "baz" => ['bar'],
  "batz" => ['end']
];

// while(list($i, $value) = each($array)) { // Try this next
foreach($array as $i => $value) {
  print $i . "\n";
  foreach($value as $index) {
    unset($array[$index]);
  }
}

print_r($array); // array('baz' => ['end'])
Run Code Online (Sandbox Code Playgroud)

双方foreachwhile会完成他们的循环和阵列" $array"将被改变.但是,foreach循环在循环时没有改变 - 所以即使我们删除它们,它仍然遍历每个元素.

更新:这个答案不是一个错误.

我认为这个答案很简单,但看起来这里的大多数用户都无法理解我在这里提到的具体细节.

使用libdom(如删除元素)或其他密集的map/list/dict过滤构建应用程序的开发人员可以证明我在这里所说的重要性.

如果你不理解这个答案,它会在某一天咬你.

  • 是.但是你总是可以使用`foreach($ array as $ key =>&$ value){}`它会给你一个元素的引用. (2认同)