Почему цикл for не выполняется, хотя условие все еще выполняется?

В следующем SSCCE, почему не for цикл выполняется для $a больше 3, хотя условие должно позволить ему выполняться до $a становится 5.

И вывод последнего утверждения еще более странный.

Я пытаюсь добиться того, чтобы элементы Select one значение для элемента / переменной word, такой что результирующий массив:

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] => ) )

2

Решение

Условие не всегда верно. Условие в вашем цикле for пересчитывает размер массива в каждой итерации. Длина массива изменяется всякий раз, когда элемент удаляется.

Значение $a а также count($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
1

Другие решения

Использовать temp переменная для итерации, когда вы сбрасываете ключ 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
}
1

По вопросам рекламы [email protected]