php-general Digest 25 Mar 2012 16:02:19 -0000 Issue 7744

Topics (messages 317257 through 317259):

Re: foreach weirdness
        317257 by: Arno Kuhl
        317258 by: Arno Kuhl

Re: Thinking out loud - a continuation...
        317259 by: Jay Blanchard

Administrivia:

To subscribe to the digest, e-mail:
        php-general-digest-subscr...@lists.php.net

To unsubscribe from the digest, e-mail:
        php-general-digest-unsubscr...@lists.php.net

To post to the list, e-mail:
        php-gene...@lists.php.net


----------------------------------------------------------------------
--- Begin Message ---
> See this following example that illustrates the problem:
> $array = array(0, 1, 2, 3, 4, 5, 6);
> foreach ($array as $index=>$value) { 
>       if ( ($index+1) < count($array) ) { 
>               $array[$index+1] += $value; 
>       } 
>       echo $value." ";
> }
> echo "<br />";
> foreach ($array as $index=>$value) { 
>       echo $value." ";
> }
> 
> You'd expect the output to be: 
> 0 1 3 6 10 15 21
> 0 1 3 6 10 15 21
> 
> But it's actually: 
> 0 1 2 3 4 5 6
> 0 1 3 5 7 9 11

Hey,

the ouput you get is right. If you want your ouput you have to rewrite your 
code.
Currently you are adding the value of the current index to the next indexes 
value (e.g. $array[0] + $array[1]; $array[1] + $array[2]; etc.).
As I understand it you want to add the current value with the next index (e.g. 
$array[0] + 1; $array[1] + 2; $array[2] + 3).
--

Hi Stephan, the first foreach loop adds the next value to the current value, 
not the next index. The reason you don't get the expected result in the first 
foreach loop is because you need to assign the $value by reference, as per the 
php manual
foreach ($array as $index=>&$value) 

But then to get the correct output from the second simple foreach loop, you 
also have to assign the $value by reference, contrary to the php manual. If you 
don't you get the wrong result and the array becomes corrupted. That could be 
classified as a bug, or at least the manual needs to elaborate on using a 
foreach when you assign the $value by reference.

Cheers
Arno


--- End Message ---
--- Begin Message ---
From: Simon Schick [mailto:simonsimc...@googlemail.com] 
Sent: 24 March 2012 12:30 AM
To: Robert Cummings
Cc: a...@dotcontent.net; php-gene...@lists.php.net
Subject: Re: [PHP] foreach weirdness

2012/3/23 Robert Cummings <rob...@interjinn.com>
>
> On 12-03-23 11:16 AM, Arno Kuhl wrote:
>>
>>
>> it still does not produce the correct result:
>> 0 1 3 6 10 15 21
>> 0 1 3 6 10 15 15
>
>
> This looks like a bug... the last row should be the same. What version 
> of PHP are you using? Have you checked the online bug reports?
>
>

Hi, Robert

Does not seem like a bug to me ...
http://schlueters.de/blog/archives/141-References-and-foreach.html

What you should do to get the expected result:
Unset the variable after you don't need this reference any longer.

Bye
Simon

--

Hi Simon, unsetting the $value does fix the problem, but I found that any time 
you assign $value by reference in a foreach loop you have to do an unset to 
avoid corrupting the array unless you continue to assign $value by reference 
(as illustrated in the article you linked).
 
So doing something as simple as:
$array = array(0, 1, 2, 3, 4, 5, 6);
foreach ($array as $key=>&$value) {
        echo "Key: $key; Value: $value<br />\n";
}

and then follow with (from the php manual):
foreach ($array as $key=>$value) {
        echo "Key: $key; Value: $value<br />\n";
}

will not only give the wrong result, it will corrupt the array for *any* 
further use of that array. I still think it’s a bug according to the definition 
of foreach in the php manual. Maybe php needs to do an implicit unset at the 
closing brace of the foreach where was an assign $value by reference, to remove 
the reference to the last element (or whatever element it was pointing to if 
there was a break) so that it doesn't corrupt the array, because any assign to 
$value after the foreach loop is completed will corrupt the array (confirmed by 
testing). The average user (like me) wouldn't think twice about reusing $value 
after ending the foreach loop, not realising that without an unset the array 
will be corrupted.

BTW thanks for that reference, it was quite an eye-opener on the pitfalls of 
using assign by reference, not only in the foreach loop.

Cheers
Arno


--- End Message ---
--- Begin Message ---
[snip]
a necessary part of building the structure. It can be removed but only as a 
post process. Why does it have to be removed? You can loop through the 
structure in JavaScript without paying heed to the key's value.
> 
> If it absolutely must go... you need to recurse through the final structure 
> replacing each "children" entry with the results of passing it through 
> array_values().
[/snip]

Unfortunately the user of the JSON will not make a change to their app. I have 
looked through the JSON to confirm that this has a particular pattern so I 
think I can just do a little regex and get it squared away. This is one of 
"those" projects. It is apparently going to be trying every step of the way.


--- End Message ---

Reply via email to