Kirby
Kirby

Reputation: 3117

php: Always losing item #1 in ArrayIterator with using ArrayIterator::offsetUnset for a current element in loop

I'm always losing second item (#1) in forearh of ArrayIterator and removing each element.

$cnt = 0;
$a = new ArrayIterator();
$a->append(++$cnt);
$a->append(++$cnt);
$a->append(++$cnt);
$a->append(++$cnt);
$a->append(++$cnt);

foreach ($a as $i => $item) {
    print_r("$i => $item".PHP_EOL);
    $a->offsetUnset($i);
}
print_r('count: '.$a->count().PHP_EOL);

foreach ($a as $i => $item) {
    print_r("lost! $i => $item".PHP_EOL);
}

Output:

0 => 1
2 => 3
3 => 4
4 => 5
count: 1
lost! 1 => 2

How it's possible? oO

$ php -v
PHP 5.5.37 (cli) (built: Jun 22 2016 16:14:46)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies

Upvotes: 2

Views: 125

Answers (2)

Pieter van den Ham
Pieter van den Ham

Reputation: 4494

Congratulations! You have found a documented bug in ArrayIterator

Extract:

ArrayIterator always skips the second element in the array when calling offsetUnset(); on it while looping through.

Using the key from iterator and unsetting in the actual ArrayObject works as expected.

Upvotes: 1

Kirby
Kirby

Reputation: 3117

Seem, there is the only to exhaust ArrayIterator with method offsetUnset. That's using do..while:

do {
    print_r("{$a->key()} => {$a->current()}".PHP_EOL);
    $a->offsetUnset($a->key());
} while ($a->count());
print_r('count: '.$a->count() . PHP_EOL);

Output:

0 => 1
1 => 2
2 => 3
3 => 4
4 => 5
count: 0

Upvotes: 0

Related Questions