2009-11-06 15 views
24

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

ループをどのように実行すればよいか聞いたことがあります:

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()を呼び出すのではなく)。

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回だけ呼び出すか、forのように2番目の関数が何度も何度も関数を呼び出すでしょうか?

+8

テストを実行してください! '関数do_something_that_returns_an_array()'が内部的に何かをエコーするようにします。 – Artelius

答えて

38

foreach()implemented using iteratorsです。したがって、配列を1回返す関数を呼び出し、既存の結果セットを指すイテレータを使用して各アイテムを続行します。

8

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

+2

その言葉はあまり正確ではありません。技術的には、PHP配列はコピーオンライトなので、配列がコピーされていると言うと、その文言は最もあいまいで最悪の誤解を招きます。戻り値は単に「そのまま」使用されます。 – cletus

0

foreach()は、IteratorオブジェクトまたはIteratorAggregateオブジェクト(インターフェイスを実装する配列やオブジェクトなど)で動作します。 不変オブジェクトでは機能しません。機能が不変オブジェクトを返すので、返す配列は、(それは、PHP自体によって作られている)foreaching前に、Iteratorオブジェクトにコピーする必要が

+0

不変==非常に定数:)あなたはPHPで関数によって返されるオブジェクトを変更することはできません、それはL値で使用することはできません(f()= 1はどちらかと思いますが、array_push(f() 、123)) –

+0

関数は不変オブジェクトを返しません。オブジェクト参照の特殊性のために、オブジェクトを逆参照して、 'getObject() - > foo = 'bar''をきれいにすることができます(オブジェクトへの参照があれば更新されます)...逆参照配列( 'getArray()['foo']'は動作しません)。しかし、PHPには不変オブジェクトのようなものはありません。オブジェクトを参照解除または変更することができます(アクセス制限は耐えられません)。 – ircmaxell

2

私は常にforループとは異なり、あります、のでdo_something_that_returns_an_array()は一度だけ実行されることを想定しましたそれが複数回実行される理由はありません。ループの真理性チェッカーが各繰り返しの最後に実行される理由は、非常に複雑なチェッカーを可能にすることです。

試験として、私は次のことをやった:

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

スクリプトは一度5を印刷。したがって、関数get_array()は1回のみ評価されます。

9

私はそれが確かにそれに答えると思います。ここで

が私のコードです:

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"; 

、ここでは結果である:

 
Case #1 
I am called. 
    Inside the loop: One => 1 
    Inside the loop: Two => 2 
    Inside the loop: Three => 3 
    Inside the loop: Four => 4 
    Inside the loop: Five => 5 

Case #2 
I am called. 
    Inside the loop: One => 1 
    Inside the loop: Two => 2 
    Inside the loop: Three => 3 
    Inside the loop: Four => 4 
    Inside the loop: Five => 5 

彼らの両方が一度関数を呼び出してください。だから違いはありません。

関連する問題