Daryl Gill
Daryl Gill

Reputation: 5524

Strange Printing on arrays

I'm testing the performances/hitches for References over copies of an array. I have the following code:

function ScoreWords($Value){
    $WordList = array(
        "Amazing" => 1,
        "Value" => 300,
        "Elements" => 30,
        "Another" => 0

    );

    if (array_key_exists($Value,$WordList)){
        return $WordList[$Value];
    }

}

$array = ["Value","Another",1,2,3,4];
echo implode(',', $array), "<br>";

foreach ($array as &$value) {
    ScoreWords($value);
}
echo implode(',', $array), "<br>";

foreach ($array as $value) {
    ScoreWords($value);
}    
echo implode(',', $array), "<br>";

But it seems, the code pasted above works semi-fine. Output is:

Value,Another,1,2,3,4

Value,Another,1,2,3,4

Value,Another,1,2,3,3

I found this by mistake as imploding was not actually necessary, but this sparks the question. Why is there a duplicated value for the final print rather than the correct value of 4? regardless of what the content of the array is. It seems to duplicate the second from last element as the last element?

Upvotes: 2

Views: 49

Answers (2)

hlscalon
hlscalon

Reputation: 7552

The thing here is that you have to unset the value when you pass it by reference:

foreach ($array as &$value) {
    ScoreWords($value);
}
unset($value); // break the reference with the last element

Warning Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

Foreach reference

Upvotes: 1

gen_Eric
gen_Eric

Reputation: 227270

What is happening is that after your 1st foreach, $value is a reference to the last element in the array. As that loop progressed it was a reference to each element, until finally stopping at the last one.

So, when the 2nd foreach runs, $value is still a reference. As that loop runs, it updates $value, which in turn, updates the last element in the array.

When it gets to the last element, it was set to 3 from the previous loop iteration. So, that's why it's set to 3 at the end.

To fix this, unset($value); after your first foreach.

Upvotes: 3

Related Questions