web-dev-qa-db-ja.com

PHP foreachループ内の配列はどのように読み取られますか?

forループで、次のことを行う方法について聞いたことがあるでしょう。

_for ($i = 0, $count = count($array); $i < $c; ++$i)
{
    // Do stuff while traversing array
}
_

これの代わりに:

_for ($i = 0; $i < count($array); ++$i)
{
    // Do stuff while traversing array
}
_

パフォーマンス上の理由から(つまり、_$count_を初期化すると、条件付きチェックごとにcount()を呼び出すのではなく、count()を1回だけ呼び出すことになります)。

foreachループで次のようにすると、違いが生じますか?

_$array = do_something_that_returns_an_array();

foreach ($array as $key => $val)
{
    // Do stuff while traversing array
}
_

これの代わりに:

_foreach (do_something_that_returns_an_array() as $key => $val)
{
    // Do stuff while traversing array
}
_

状況が私にどちらかを使用することを許可すると仮定しますか?つまり、PHPは、どちらの場合も1回だけ関数を呼び出すのですか、それとも2番目のケースが関数を何度も呼び出すforのようなものですか?

24
BoltClock

foreach() is イテレータを使用して実装 -したがって、配列を1回返す関数を呼び出すだけで、既存の結果セットを指すイテレータを使用して各項目を続行します。

38
Amber

それをテストすることは確かにそれに答えると思います。

これが私のコードです:

function GetArray() {
    echo "I am called.\n";
    return array("One"=>1, "Two"=>2, "Three"=>3, "Four"=>4, "Five"=>5);
}

echo "Case #1\n";
$array = GetArray();
foreach ($array as $key => $val){
    // Do stuff while traversing array
    echo "    Inside the loop: $key => $val\n";
}
echo "\n";

echo "Case #2\n";
foreach (GetArray() as $key => $val) {
    // Do stuff while traversing array
    echo "    Inside the loop: $key => $val\n";
}
echo "\n";

結果は次のとおりです。

ケース#1 
呼び出されました。
ループ内:1 => 1 
ループ内:2 => 2 
ループ内ループ:3 => 3 
ループ内:4 => 4 
ループ内:5 => 5 
 
ケース#2 
私は呼ばれています。
ループの内側:1 => 1 
ループの内側:2 => 2 
ループの内側:3 => 3 
ループ:4 => 4 
ループの内側:5 => 5 

どちらも呼び出し関数を1回読み取ります。だから違いはありません。

9
NawaMan

foreachは入力配列のコピーを作成し、各反復でそれを処理します。したがって、foreach (do_something_that_returns_an_array() as $key => $val)を使用すると、do_something_that_returns_an_array()が1回だけ呼び出されます。

8
deceze

何が起こるかを見るために例を設定します。何かのようなもの...

function do_something_that_returns_an_array() {
    echo 'I have been called!'; 
    return array('i am an', 'array');
}

CodePadで確認できるように、呼び出されるのは1回だけです

4
alex

do_something_that_returns_an_array()は、forループとは異なり、複数回実行する理由がないため、1回だけ実行されると常に想定してきました。 forループの真理チェッカーがすべての反復の最後に実行される理由は、非常に複雑なチェッカーを許可するためです。

テストとして、私は次のことを行いました。

_function get_array() {echo 5; return array(1,2,3,4,5);}
foreach(get_array() as $key => $value) {}
_

スクリプトは5回印刷しました。したがって、関数get_array()は1回だけ評価します。

2
Steven

foreach()は、IteratorまたはIteratorAggregateオブジェクト(たとえば、インターフェイスを実装する配列やオブジェクト)で機能します。 immutableオブジェクトでは機能しません。関数は不変オブジェクトを返すため、返す配列は、foreachする前にIteratorオブジェクトにコピーする必要があります(php自体によって作成されます)

0
Valentin Golev