web-dev-qa-db-ja.com

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

最近、私はこの奇妙な問題を経験しました:

while(list($key, $value) = each($array))

置換するすべての配列値をリストしていませんでした...

foreach($array as $key => $value)

...完璧に機能しました。

そして、私は今興味があります..これら2つの違いは何ですか?

35
jolt

以前にアレイを横断しましたか? each()は配列内での位置を記憶しているので、reset()をしないとアイテムを見逃す可能性があります。

_reset($array);
while(list($key, $value) = each($array))
_

配列トラバーサルのこの方法の価値は古く、より慣用的なforeachに取って代わられました。一度に1項目ずつの性質を利用したい場合を除き、使用しません。

arrayeacharray&$ array)

配列から現​​在のキーと値のペアを返し、配列カーソルを進めます。

each()が実行された後、配列カーソルは配列の次の要素に残されるか、配列の最後に到達した場合は最後の要素を過ぎます。 eachを使用して配列を再度走査する場合は、reset()を使用する必要があります。

(出典: PHPマニュアル

53
John Kugelman

1つの違いは、each()は配列に対してのみ機能することです(適切にのみ機能します)。 foreachは、 traversable インターフェイスを実装するすべてのオブジェクトで機能します(もちろん、組み込みの配列型も含まれます)。

Foreachにマイクロ最適化がある場合があります。基本的に、foreachは次のものと同等です。

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

一方、eachは基本的に次のことを行います。

$return = $array->valid() ? array($array->key(), $array->current()) : false;
$array->next();
return $return;

したがって、3行は両方とも同じです。どちらも非常に似ています。 eachtraversableインターフェイスを心配する必要がないという点で、いくつかのマイクロ最適化があるかもしれません...しかし、それはせいぜいマイナーです。ただし、ブールキャストを実行してphpコードとforeachのコンパイル済みCをチェックすることで相殺されます...言うまでもなくwhile/eachコードでは、2つの言語構造と1つの関数を呼び出していますが、foreachでは単一の言語構造です...

言うまでもなくforeachは非常に読みやすいですIMHO ...読みやすく、より柔軟なことは、-to me- foreachが明確な勝者であることを意味します。 (それはeachには用途がないと言っているわけではありませんが、個人的には必要ありません)...

13
ircmaxell

警告! 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'])

foreachwhileの両方がループと配列「$array "は変更されます。ただし、foreachループはループ中に変更されませんでした。したがって、それらを削除したにもかかわらず、すべての要素を繰り返し処理しました。

更新:この答えは間違いではありません。

この答えは非常に簡単だと思いましたが、ここのユーザーの大部分はここで言及した具体的な詳細を理解できないようです。

Libdom(要素の削除など)または他の集中的なmap/list/dictフィルタリングを使用してアプリケーションを構築した開発者は、ここで述べたことの重要性を証明できます。

この答えを理解していないと、いつかあなたに噛まれてしまいます。

9
Xeoncross

eachを反復するオブジェクトに渡した場合、PHPマニュアルは、予期しない結果が生じる可能性があることを警告します。

$array

1
Dan McGrath