Sam
Sam

Reputation: 41

Using unset() function in an array to delete elements

Trying to delete all elements in the array (given below) which are less then 0 using the following code:

 <?php 
       $arr=array(1,2,3,4,5,-6,-7,-8,-9,-10);

        for ($i=0;$i<count($arr);$i++){
                if ($arr[$i]<0) {
                unset($arr[$i]);
                }
        }

    var_dump($arr);

    echo '<pre>', print_r($arr), '</pre>';

    ?>

However, the result is the following:

array(7) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) [4]=> int(5) [8]=> int(-9) [9]=> int(-10) }
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
    [8] => -9
    [9] => -10
)
1

Quite confused why not all the elements which are less then 0 are removed from the array. Any thoughts on this?

Upvotes: 4

Views: 118

Answers (6)

AbraCadaver
AbraCadaver

Reputation: 79014

Adding to the excellent foreach and array_filter answers (which detail the issue), using your existing loop, just count first so that it can't change each iteration:

$arr=array(1,2,3,4,5,-6,-7,-8,-9,-10);

$c = count($arr);

for ($i=0; $i<$c; $i++){
    if ($arr[$i]<0) {
        unset($arr[$i]);
    }
}

Upvotes: 2

Don&#39;t Panic
Don&#39;t Panic

Reputation: 41820

If you really need to do it in a loop, you can avoid that problem by using a foreach loop instead.

foreach ($arr as $key => $value) {
    if ($value < 0) {
        unset($arr[$key]);
    }
}

Removing elements as you iterate shouldn't cause any problems this way.

Upvotes: 4

Syscall
Syscall

Reputation: 19764

You could do this using array_filter(). The second parameter is an anonymous function that takes as argument an element of the array. Inside, you have to determine weither it should be kept or not.

$arr=array(1,2,3,4,5,-6,-7,-8,-9,-10);
$arr = array_filter($arr, function($e) {
    return $e >= 0 ; // keep only element greater than zero
});
echo '<pre>', print_r($arr), '</pre>';

Outputs :

array(5) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
  [4]=>
  int(5)
}

Upvotes: 2

ZeissS
ZeissS

Reputation: 12135

You are iterating using count($arr) which is reevaluated after each iteration. Since you remove an item, the array gets shorter. At the same time you increment your iterator. This works out until you reach the second last item, where deleting that item and increment the counter makes the loop condition false, thus skipping the last elements.

You can do an echo in the loop to print $i and count($arr) to see the details.

Upvotes: 3

Spencer Wieczorek
Spencer Wieczorek

Reputation: 21575

This is because you are manipulating the array while you are positively iterating through it, which can make it off-set and skip elements. One common way to solve this is to do the loop backwards:

   $arr=array(1,2,3,4,5,-6,-7,-8,-9,-10);

    for ($i=count($arr)-1;$i>=0;$i--){
            if ($arr[$i]<0) {
            unset($arr[$i]);
            }
    }

var_dump($arr);

echo '<pre>', print_r($arr), '</pre>';

Upvotes: 2

Phil
Phil

Reputation: 164946

This is what usually happens when you remove elements while iterating forwards through a collection. You end up missing elements because you're trying to iterate a moving target. One solution would be to iterate backwards

for ($i = count($arr) - 1; $i >= 0; $i--)

Another would be to simply use array_filter to create a new array

$newArr = array_filter($arr, function($num) {
    return $num >= 0;
});

Upvotes: 4

Related Questions