30

i want to have a foreach loop where the initial array is changed inside the loop.

eg.

$array = array('red', 'blue');
foreach($array as $key => $value) {
    $array[] = 'white';
    echo $value . '<br />';
}

in this loop the loop will print out red and blue although i add another element inside the loop.

is there any way to change the initial array inside the loop so new elements will be added and the foreach will use the new array whatever is changed?

i need this kind of logic for a specific task:

i will have a if statement that search for a link. if that link exists, it is added to the array. the link content will be fetched to be examined if it contains another link. if so, this link is added, and the content will be fetched, so on so forth.. when no link is further founded, the foreach loop will exit

1
  • 1
    Do you figure out that without any break or so, your idea will run into an infinite loop? Commented Feb 27, 2010 at 16:45

5 Answers 5

45

I don't think this is possible with a foreach loop, at least the way you wrote it : doesn't seem to just be the way foreach works ; quoting the manual page of foreach :

Note: Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself.


**Edit : after thinking a bit about that note, it is actually possible, and here's the solution :**

The note says "Unless the array is referenced" ; which means this portion of code should work :

$i = 0;
$array = array('red', 'blue');
foreach($array as $key => & $value) {
    $array[] = 'white';
    echo $value . '<br />';
    if ($i++ >= 5) {
        break;   // security measure to ensure non-endless loop
    }
}

Note the & before $value.

And it actually displays :

red
blue
white
white
white
white

Which means adding that & is actually the solution you were looking for, to modify the array from inside the foreach loop ;-)


**Edit : and here is the solution I proposed before thinking about that note :**

You could do that using a while loop, doing a bit more work "by hand" ; for instance :

$i = 0;

$array = array('red', 'blue');

$value = reset($array);
while ($value) {
    $array[] = 'white';
    echo $value . '<br />';
    if ($i++ >= 5) {
        break;   // security measure to ensure non-endless loop
    }
    $value = next($array);
}

Will get you this output :

red
blue
white
white
white
white
Sign up to request clarification or add additional context in comments.

9 Comments

hmm why 4 white? i only want the added value to be iterated one time
In the examples I posted, you get 4 white because of the security counter I used to prevent endless looping : the break will force the loop to end after 6 iterations (The code you provided in your question was causing an endless loop, and I didn't want that in my examples) ;;; in your application, up to you to find a solution that suits your need to avoid endless looping :-) (judging from your question, you have ; even if you didn't include it as a part of your question)
don't really understand why $value is referenced and not $array ...but it's good if it works... did you test this code ? Cheers.
@DCC : if I say "And it actually displays", it means I tested the code, to get what's displayed ;-) ;;; about $value and $array and which one gets the &... Well, I can't say much about that : it's the syntax that PHP accepts for foreach loops ^^
Dont forget to unset($value); after you're out of the foreach, though - else the next time you use $value in another foreach loop, you could get some weird behavior.
|
9

What you need to do is move the assignment inside the for loop and check the length of the array every iteration.

$array = array('red', 'blue');
for($i = 0; $i < count($array); $i++)
{
   $value = $array[$i];
   array_push($array, 'white');
   echo $value . '<br />';
}

Be careful, this will cause an infinite loop (white will be added to the end of the array at every loop).

1 Comment

Whilst the previous answer has been accepted, this actually worked much better for me to accomplish the goal of affecting an array from within a loop. Using the above answer (the "correct" one) kept resetting the pointer within the array causing all sorts of issues. Use this one. To the writer, thanks, and please not the $array[$i] is misreferenced in your answer.
4

Maybe you should use some other way, like:

$ar = array('blue', 'red');
while ($a = array_pop($ar) {
     array_push($ar, 'white');
}

Or something like this...

3 Comments

how do u ensure that white only is added and printed out one time? cause your code gives an infinite loop
I did not. As pointed as comment to the question, is up to the programmer to write smart code... Obviously as written by me it will run forever, it's just an example.
@noname you can use if .. else... before an array_push, and in_array to check if it is already on a duplicate array that just keeps "record" :)
1

You can access the array by using the $key

$array = array('red', 'blue');
foreach($array as $key => $value) {
    $array[$key] = 'white';
}

1 Comment

you didn't understand the question, this is not an answer
1

In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference. [source]

All you have to do to your old code is

precede $value with &

like so

$array = array('red', 'blue');
foreach($array as $key => &$value) {// <-- here
    $array[] = 'white';
    echo $value . '<br />';
}

A while loop would be a better solution.

while (list ($key, $value) = each ($array) ) {
    $array[] = 'white';
    echo $value . '<br />';
}

If you don't need the $key variable, as your example suggests then using $value = array_pop($array) instead if list ($key, $value) = each ($array) would be a less expensive option. see @enrico-carlesso's Answer Here

As your array is sequantial(numeric,indexed) and not associative then you could use a for loop instead.

for ($key = 0; $key < count($array); ++$key) {
    $value = $array[$i];

    $array[] = 'white';
    echo $value . '<br />';
}

As a side note.

I don't understand why its &$value and not &array.

&$value would suggest you can only modify the current element within the loop. &array would suggest you could modify all array elements within the loop, including adding/removing element.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.