|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-10-29 13:49 UTC] fra dot casula at gmail dot com
Description: ------------ A nested foreach on the same iterator doesn't produce the same result that is produced when using plain arrays. The nested foreach should call seek() to reset the internal pointer to its correct position so that the first foreach can resume where it stopped. Test script: --------------- http://pastebin.com/EQrUZ7AQ Expected result: ---------------- I expect to see the same output for all four cases in the example code. The expected output is: first loop 0 second loop 0 second loop 1 second loop 2 first loop 1 second loop 0 second loop 1 second loop 2 first loop 2 second loop 0 second loop 1 second loop 2 Actual result: -------------- first loop 0 second loop 0 second loop 1 second loop 2 PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2026 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 06 06:00:01 2026 UTC |
I get what you're saying, arrays are by value. Objects, starting from PHP5, are by reference. Still if I unset an element of the same array in the nested foreach I get that element wiped in the main array as well. $a = [1, 2, 3, 4]; foreach ($a as $i => $v) { foreach ($a as $i2 => $v2) { if ($i2 % 2 == 0) { unset($a[$i2]); } } } var_dump($a); // it prints 2, 4 (of course) If each foreach is working with its own array copy like you said then there's probably a scope issue? The whole thing is confusing because someone would think that iterators work just like a normal array but then, even if we don't implement a thing and use the ready-to-use ArrayIterator class, we get a completely different behaviour with a simple thing like a nested foreach. It's not just a completely different behaviour, it's just unreliable. The ArrayIterator class, as it is, can't even be used in a nested foreach unless we start setting positions manually. That would probably make us loose the benefit of using iterators in the first instance.When you unset $a[$i2], you're removing the element from $a, not from the copy being iterated over. Each loop starts by getting a copy of $a as it exists at that moment. $a = [1,2,3,4]; foreach ($a as $i => $v) { echo 'outer loop: ', $v, ' ', join(",", $a),"\n"; foreach ($a as $i2 => $v2) { echo 'inner loop: ', $v2, ' ', join(",", $a),"\n"; if ($i2 % 2 == 0) { echo "Drop $i2\n"; unset($a[$i2]); } } }