Мы все слышали о том, как в цикле 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()
с каждой условной проверкой).
Это также имеет значение, если в цикле 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 вызывает функцию только один раз в обоих случаях, или это похоже for
где второй случай будет вызывать функцию снова и снова?
foreach()
реализуется с использованием итераторов – поэтому он вызывает только функцию, которая возвращает массив один раз, а затем использует итератор, который указывает на существующий набор результатов для продолжения с каждым элементом.
Я думаю, что тестирование на это обязательно ответит.
Вот мой код:
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 Меня позвали. Внутри цикла: One => 1 Внутри цикла: Two => 2 Внутри цикла: Три => 3 Внутри цикла: Four => 4 Внутри цикла: Five => 5 Случай №2 Меня позвали. Внутри цикла: One => 1 Внутри цикла: Two => 2 Внутри цикла: Три => 3 Внутри цикла: Four => 4 Внутри цикла: Five => 5
Оба они одновременно считывают функцию вызова. Так что ничего другого.
foreach
делает копию входного массива и работает на нем на каждой итерации. Поэтому вы можете использовать foreach (do_something_that_returns_an_array() as $key => $val)
и он будет вызывать do_something_that_returns_an_array()
только один раз.
Я бы привел пример, чтобы узнать, что произойдет. Что-то вроде…
function do_something_that_returns_an_array() { echo 'I have been called!'; return array('i am an', 'array'); }
Как вы можете видеть на CodePad, он вызывается только один раз .
Я всегда предполагал, что do_something_that_returns_an_array()
работает только один раз, потому что, в отличие от цикла for, нет причин для его запуска несколько раз. Причина, по которой средство проверки правильности цикла работает в конце каждой итерации, заключается в том, чтобы допускать очень сложные проверки.
В качестве теста я сделал следующее:
function get_array() {echo 5; return array(1,2,3,4,5);} foreach(get_array() as $key => $value) {}
Сценарий напечатал 5 раз. Поэтому функция get_array()
оценивает только один раз.
foreach () работает с объектами Iterator или IteratorAggregate (например, массивы и объекты, реализующие интерфейс). Он не может работать с неизменяемыми объектами. Функции возвращают неизменяемые объекты, поэтому возвращаемый массив должен быть скопирован в объект Iterator перед тем, как он будет выполняться (это делается самим php)