php - цикл while повторяется в два раза дольше, чем ожидалось, а вложенный цикл for повторяется в 1,5 раза чаще, чем ожидалось

Этот скрипт должен получать многомерный массив и перебирать значения.

Размер массива равен 10, и каждый элемент должен содержать ассоциативный массив:

$games[0] => array('foo' => 'bar')
$games[1] => array('foo1' => 'bar1')
etc..

В этом примере цикл while должен повториться 5 раз. Цикл for должен повторяться 10 раз для каждой итерации цикла while.

Итак, я ожидаю, что эхо будет:

countwhile = 5 countfor = 50 totalgames = 50

но я на самом деле получаю

countwhile = 5 countfor = 150 totalgames = 150

Я считаю, что массив $games не является проблемой, потому что я уже делал этот вызов ниже и использовал print_r для просмотра содержимого, и это соответствует ожиданиям.

Весь этот код не находится в функции или классе, как на моей странице index.php, может ли проблема быть связана с областями переменных?

$totalruns = 5;  
$endindx = 10;
$startindx = 0;
$countwhile = 0;
$countfor = 0;
$totalfilesize = 0;
$totalgames = 0; 
$sizeof = 0; 

while($totalruns > 0)  
{  
     $games = $feedHandler->getGames($startindx, $endindx);  
     $sizeof = sizeof($games);  

     for($i=0; $i<$sizeof; $i++)  
     {  
          $totalfilesize += $games[$i]['swf_file_size'];
          $countfor++;  
     }  

     $startindx += 10;
     $endindx += 10;  
     $totalruns -= 1;  
     $totalgames += $sizeof;
     unset($games);  
}  

echo'<p>' . ' countwhile = ' . $countwhile . ' countfor = ' . $countfor . '</p>';

person Anish    schedule 30.12.2010    source источник
comment
Святой запутанный код. Это может помочь дать вам осмысленные имена переменных вместо алфавита. И sizeof — это псевдоним count(), к вашему сведению. Сейчас я играю с этим, но посмотрите, сможете ли вы за это время почистить это (вероятно, вы получите больше желающих помочь вам).   -  person Brad Christie    schedule 30.12.2010
comment
почему вы устанавливаете $sizeof = sizeof($games) для каждой итерации? вы можете сделать подсчет перед циклом, вы даже можете использовать $e, поскольку вы перезаписываете $e в каждом цикле (поэтому последний $e += $e бесполезен)   -  person regilero    schedule 30.12.2010
comment
Я отредактировал этот пост с обновленным кодом, присвоив всем переменным значимые имена.   -  person Anish    schedule 30.12.2010
comment
Кто-нибудь может объяснить, почему $countfor и $totalgames равны 150 вместо 50? Я снова попробовал этот цикл без unset($games) и получил тот же результат, когда я print_r($games) я получаю массив с 50 элементами, как и ожидалось.   -  person Anish    schedule 30.12.2010


Ответы (3)


Как я сказал в своем комментарии, $e перезаписывается в каждом цикле, поэтому то, что у вас есть в $e в конце, — это просто последнее количество элементов в $games *2. Добавленный с ajreal проблемами, это означает, что результаты - это то, что ваш код должен отображать :-), и я совершенно уверен, что ваша последняя $game состоит не просто из 10 элементов, а из 50. Тихо, конечно... но это трудно читать.

person regilero    schedule 30.12.2010
comment
ну, я бы сказал, МЫ были правы, а вы несколько раз ошибались :-) - person regilero; 30.12.2010
comment
только потому, что этот правильный ответ решил вашу насущную проблему, я не думаю, что это должен быть принятый ответ. простое решение непосредственной проблемы не делает этот код лучше! - person markus; 31.12.2010

проблема 1:

$sizeof = sizeof($games)-1;

объяснить 1:

for($i=0, $sizeof = sizeof($games);$i<=$sizeof;$i++)  

вышеприведенное будет выполнено 11 раз, если sizeof($games) равно 10
Итак, либо

for($i=1, $sizeof = sizeof($games);$i<=$sizeof;$i++)  

or

for($i=0, $sizeof=sizeof($games)-1;$i<=$sizeof;$i++)  

проблема 2:

$e = sizeof($games);

объясните 2:

$e = count($games);  
...
$e += $e;

Если окончательный размер $games равен 50, вы просто суммируете его до 100
, так что это какая-то логическая проблема.

person ajreal    schedule 30.12.2010

Я знаю, что ответ был принят, но подумал, что проведу рефакторинг и сделаю это немного чище.

function retrieveGamesInfo($limit, $start = 0)
{
  $feedHandler = new FeedHandler(); // ignore this, just for testing to simluate your call

  if ($start > $limit)
    throw new Exception("Start index must be within the limit");

  $result = Array(
    'TotalGames' => 0,
    'TotalFileSize' => 0
  );

  // iterate over the results in groups of 10
  $range = $start;
  while ($range < $limit)
  {
    $range_end = $range + 10; // change me to play with the grab amount
    if ($range_end > $limit)
      $range_end = $limit;

    // grab the next 10 entries
    $games = $feedHandler->getGames($range,$range_end);

    $result['TotalGames'] += count($games);

    foreach ($games as $game)
      $result['TotalFileSize'] += $game['swf_file_size'];

    $range = $range_end;
  }
  return $result;
}
var_dump(retrieveGamesInfo(50));

на основе всего, что я прочитал и усвоил, это должно быть хорошим дополнением. Вышеизложенное дает следующий результат:

array(2) {
  ["TotalGames"]=>
  int(50)
  ["TotalFileSize"]=>
  int(275520)
}
person Brad Christie    schedule 30.12.2010