0
$array = array('1','3','20','10');
foreach ($array as $i=>$arr) {
   if ($i==0) unset($array[$i]);
}

Question: would removing one element mess up the order of the iteration of this loop? What happen when I remove the element with the index smaller/equal/bigger than the current iterating index?

What should I avoid to do when modifying the original array while iterating over it?

Edit: In case the array is passed by reference?

4
  • You could've just make a sandbox script and fiddle with it to see what happens in the said scenario. In my opinion, iterating trough array then removing items later in stack is indication something is quite wrong with the logic here... but that is my opinion Commented Aug 30, 2012 at 10:27
  • 1
    In this particular use case you're better off using array_filter to remove elements from an array that meet some particular criteria Commented Aug 30, 2012 at 10:28
  • As @GordonM mentioned using an array_filter is better idea. However even if you decide to do it in the above manner it would not be an issue since foreach works on a copy of the array and therefore deleting elements while iterating will not mess the order. You cannot pass an array reference to foreach, only reference of values so that modifying the value will reflect in the original array as well. Commented Aug 30, 2012 at 12:42
  • A mistake in the above comment, array references can be passed to a foreach loop. Commented Aug 30, 2012 at 13:33

2 Answers 2

1

Particularly to your provided code, once

$array = array('1','3','20','10');

is declared, the keys are bound, so

if($i==0) unset($array[$i]);

will only unset '1', and you will be left with

array(2) {
  [1]=>
  string(1) "2"
  [2]=>
  string(1) "3"
}

And as @cleong said, PHP seems to create a copy of the array when iterating:

$arr=array("1","2","3");
foreach($arr as $idx=>$val)
{
    if(isset($arr[1])) unset($arr[1]);
    echo $val."\n";
}
var_dump($arr);

will return

1
2
3
array(2) {
  [0]=>
  string(1) "1"
  [2]=>
  string(1) "3"
}

So it's "OK" to unset elements inside an iteration, as long as the unset would not generate error (e.g. unsetting an already unset variable).

But, I don't think this is a good idea. If your question is "how to avoid this", provide an example of why you have to do this.

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

2 Comments

I have to do it because, in case I have to iterate an big array (>50000 loop) to calculate statistics, I want to free the memory to have enough memory to do other things.
@ThanhTrung Are you actually facing a huge memory consumption? Microtweaking in programming is not a good idea in many case. 50000 loop doesn't seem to be hard for modern computers.
0

PHP creates a copy of the array when you use a foreach loop(). Even if you blow away the array entirely, the iteration will continue as through nothing has happened. To wit:

$array = array("a", "b", "c");

foreach($array as $element) {
    $array = null;
    echo "$element ";
}

Output:

a b c

3 Comments

Does it mean that the amount of memory allocated is 2x bigger? One for $array and other for the copy of $array. What will happen if the array is passed by reference?
@ThanhTrung If you pass a reference of the array then the structure will not be copied but only the values. This article explains the inner workings of foreach loop in a clear and concise manner nikic.github.com/2011/11/11/…
@ThranhTrung Yes and no. A shallow copy of the array will always be created when you use foreach(). Since only reference to the objects in the array are copied, it doesn't exactly duplicate the memory requirement. The copying is fast, such that a foreach() loop will almost always outpace other means. It's not something to worry about.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.