为什么这个 for 循环似乎不执行,尽管条件仍然为真?

Why doesn't this for loop seem to execute although the condition is still true?

在下面的SSCCE中,为什么$a大于3时不执行for循环,虽然条件应该让它执行到$a变为5.

而最后一条语句的输出更加诡异。

我想要实现的是,我想删除 element/variable word 具有 Select one 值的元素,这样得到的数组是:

Array ( [0] => stdClass Object ( [word] => alpha [sentence] => A is the first letter in the word Alpha. ) [1] => stdClass Object ( [word] => beta [sentence] => B is the first letter in the word Beta. ) )

问题是什么东西弄乱了它,我该怎么做才能解决它?

<?php 

$objectOne = new stdClass;
$objectOne->word = 'alpha';
$objectOne->sentence = 'A is the first letter in the word Alpha.';

$objectTwo = new stdClass;
$objectTwo->word = 'beta';
$objectTwo->sentence = 'B is the first letter in the word Beta.';

$objectThree = new stdClass;
$objectThree->word = 'Select one';
$objectThree->sentence = '';

$items = array($objectOne, $objectTwo, $objectThree, $objectThree, $objectThree, $objectThree );


print_r($items);//check
echo '<br><br>count($items) >> '.count($items).'<br><br>';//check


for ($a=0; $a < count($items); $a++) {
    echo '<br><br>We are entering index '.$a.'<br><br>';//check
    echo '<br>'.$items[$a]->word.'<br>';//check

    if ( ($items[$a]->word)=="Select one"  ) {
        echo '<br>YES if ( ($items['.$a.']->word)=="Select one"  ) AT '.$a.' INDEX.<br>';//check
        unset($items[$a]);
        /**/array_splice($items, $a, 1);
    }

    echo '<br><br>We are leaving index '.$a.'<br><br>';//check
}


echo '<br><br>AFTER:-<br>';//check
print_r($items);//check

?>

输出:

Array ( [0] => stdClass Object ( [word] => alpha [sentence] => A is the first letter in the word Alpha. ) [1] => stdClass Object ( [word] => beta [sentence] => B is the first letter in the word Beta. ) [2] => stdClass Object ( [word] => Select one [sentence] => ) [3] => stdClass Object ( [word] => Select one [sentence] => ) [4] => stdClass Object ( [word] => Select one [sentence] => ) [5] => stdClass Object ( [word] => Select one [sentence] => ) )

count($items) >> 6



We are entering index 0


alpha


We are leaving index 0



We are entering index 1


beta


We are leaving index 1



We are entering index 2


Select one

YES if ( ($items[2]->word)=="Select one" ) AT 2 INDEX.


We are leaving index 2



We are entering index 3


Select one

YES if ( ($items[3]->word)=="Select one" ) AT 3 INDEX.


We are leaving index 3



AFTER:-
Array ( [0] => stdClass Object ( [word] => alpha [sentence] => A is the first letter in the word Alpha. ) [1] => stdClass Object ( [word] => beta [sentence] => B is the first letter in the word Beta. ) [2] => stdClass Object ( [word] => Select one [sentence] => ) ) 

使用 temp 变量进行迭代,因为在 for 执行期间取消设置 main 的键。也许,这应该有效:-

$temp = $items;
for ($a=0; $a < count($temp); $a++) {
  echo '<br><br>We are entering index '.$a.'<br><br>';//check
  echo '<br>'.$items[$a]->word.'<br>';//check

  if ( ($items[$a]->word)=="Select one"  ) {
      echo '<br>YES if ( ($items['.$a.']->word)=="Select one"  ) AT '.$a.' INDEX.<br>';//check
      unset($items[$a]);
      /**/array_splice($items, $a, 1);
  }

  echo '<br><br>We are leaving index '.$a.'<br><br>';//check
}

条件并不总是正确的。 for 循环中的条件会在每次迭代中重新计算数组的大小。每当删除一个项目时,数组的长度都会改变。

$acount($items)每次条件检查的值如下:

$a | count($items) | $a < count($items)
---------------------------------------
 0 | 6             | true 
 1 | 6             | true
 2 | 6             | true
 3 | 5             | true  -- $items[2] was removed
 4 | 4             | false -- $items[3] was removed

您应该将数组的大小存储在一个变量中并使用它。此外,由于 array_splice 不保留数字键,您最终会在尝试访问 $items[4]$items[5] 时收到未定义的偏移通知。该行不是必需的。

$count = count($items);
for ($a=0; $a < $count; $a++) {

更好的是,您可以使用 foreach 代替 for 并使用 $item 代替 $items[$a]:

foreach ($items as $a=>$item) {
    echo '<br><br>We are entering index '.$a.'<br><br>';//check
    echo '<br>'.$item->word.'<br>';//check
    ...
    unset($items[$a]); //can't use $item because it is a copy and not a reference