Производительность функции PHP foreach

Кто-нибудь знает, если это сделать

foreach ($user->getFriends() as $friend) {
  // Do something.
}

Заставляет PHP вызывать функцию getFriends() в объекте пользователя несколько раз и, следовательно, это будет более эффективно?

$friends = $user->getFriends();
foreach ($friends as $f) {
 // Do something.
}

Ответы

Ответ 1

foreach использует результат выражения $user->getFriends(). Вы можете посмотреть на это следующим образом:

foreach (($user->getFriends()) as $friend) {
    // ...
}

Функция не будет вызываться более одного раза, поскольку вы передаете ее результат, а не саму функцию. foreach не знает о функции.

Ответ 2

Я не думаю, что метод getFriends() в этом случае будет вызываться несколько раз.

foreach делает копию массива для перебора, а затем выполняет итерацию над копией. Нет причин для вызова вашего метода более одного раза.

Само копирование (и результирующее использование памяти) - это то, что вы должны учитывать при использовании цикла foreach.

Ответ 3

Вот код для скамьи:

srand();
$asize = 1000000;
$a = array();
for ($x=1;$x<=$asize;$x++) $a[]=rand();


$i=0;
$s = microtime(true);
foreach($a as $k=>$v) {
    ++$a[$k];
}
$e = microtime(true);
dolog($s,$e,'FOREACH-KEY');

$i=0;
$s = microtime(true);
foreach($a as &$v) {
    ++$v;
}
$e = microtime(true);
dolog($s,$e, 'FOREACH-PTR');

$i=0;
$s = microtime(true);
for ($x=0;$x<$asize;$x++){
    ++$a[$x];
}
$e = microtime(true);
dolog($s,$e,'FOR');

function awpp(&$item,$key){
    ++$item;
}

$s = microtime(true);
array_walk($a, 'awpp');
$e = microtime(true);
dolog($s,$e,'ARRAY_WALK');

reset($a);
$s = microtime(true);
while (list($k, $v) = each($a)) {
    ++$a[$k];
}
$e = microtime(true);
dolog($s,$e,'EACH');

reset($a);
$s = microtime(true);
$node = current($a);
++$node;
while($node=next($a)) {
    ++$node;
}
$e = microtime(true);
dolog($s,$e,'NEXT');

И результат:

FOREACH-KEY Start: 1367595478.8087210655, End: 1367595479.2945981026, DIFF: 0.4858770370
FOREACH-PTR Start: 1367595479.2946701050, End: 1367595479.4266710281, DIFF: 0.1320009232
FOR Start:         1367595479.4267220497, End: 1367595479.6769850254, DIFF: 0.2502629757
ARRAY_WALK Start:  1367595479.6770300865, End: 1367595481.1930689812, DIFF: 1.5160388947
EACH Start:        1367595481.1931140423, End: 1367595482.5088000298, DIFF: 1.3156859875
NEXT Start:        1367595482.5088429451, End: 1367595483.2801001072, DIFF: 0.7712571621

Итак, быстрее foreach с указателем и без значения ключа.

Ответ 4

Это зависит от того, как вы хотите использовать базовые данные. Поскольку вы повторяете самую быструю задачу - использовать цикл for, предопределяя его верхнюю границу (поэтому вы arent, скажем, итерации функции count).

$limit=count($records);
for ( i=0; $i<$limit; i++){
    // do this code;
}