0

I'm removing values from an array in PHP use an in_array check yet for some reason it does not want to check through the entire length of the exclude array. Running this code it removes the Dodge entries from the array but not the Toyota, why is this?

<?php

    $inventory = array(
        '0' => Array
            (
                'car_name' => 'Dodge',
                'set_name' => 'A',
                'edition' => 'B41',
                'location' => 'Houston'
            ),

        '1' => Array
            (
                'car_name' => 'Dodge',
                'set_name' => 'A',
                'edition' => 'B41',
                'location' => 'Houston'
            ),

        '2' => Array
            (
                'car_name' => 'Dodge',
                'set_name' => 'A',
                'edition' => 'B41',
                'location' => 'Houston'
            ),

        '3' => Array
            (
                'car_name' => 'Dodge',
                'set_name' => 'A',
                'edition' => 'VarA31',
                'location' => 'Houston'
            ),

        '4' => Array
            (
                'car_name' => 'Toyota',
                'set_name' => 'A',
                'edition' => 'VarA31',
                'location' => 'Houston'
            ),

        '5' => Array
            (
                'car_name' => 'Toyota',
                'set_name' => 'A',
                'edition' => 'VarA31',
                'location' => 'Houston'
            ),

        '6' => Array
            (
                'car_name' => 'Toyota',
                'set_name' => 'A',
                'edition' => 'VarA31',
                'location' => 'Houston'
            ),

        '7' => Array
            (
                'car_name' => 'Toyota',
                'set_name' => 'A',
                'edition' => 'VarA31',
                'location' => 'Houston'
            ),

        '8' => Array
            (
                'car_name' => 'Toyota',
                'set_name' => 'A',
                'edition' => 'VarA31',
                'location' => 'Houston'
            ),

        '9' => Array
            (
                'car_name' => 'Toyota',
                'set_name' => 'A',
                'edition' => 'VarA31',
                'location' => 'Houston'
            ),

        '10' => Array
            (
                'car_name' => 'Toyota',
                'set_name' => 'A',
                'edition' => 'VarA31',
                'location' => 'Houston'
            ),

        '11' => Array
            (
                'car_name' => 'Toyota',
                'set_name' => 'A',
                'edition' => 'VarA31',
                'location' => 'Houston'

            ),
    );

    $exclude = array('Dodge','Toyota');

    for($k=0; $k<sizeof($inventory); $k++)
    {
    if(in_array(trim($inventory[$k]['car_name']), $exclude))
    {   unset($inventory[$k]);}

    }

         $inventory = array_values($inventory);
         echo '<pre>';
         print_r($inventory);
         echo '</pre>';



    ?>
Undermine2k
  • 1,481
  • 4
  • 28
  • 52
  • in_array() does not work on multidimensional arrays. Possible duplicate of [this question](http://stackoverflow.com/questions/4128323/in-array-and-multidimensional-array) – AndrewVT Dec 28 '14 at 00:33
  • 4
    @user2058037 - in_array is being used on the $exclude array here, where it will work – Mark Baker Dec 28 '14 at 00:34
  • 1
    This is a good example of why incremental `for` loops are not often used in languages supporting some kind of `foreach` construct. If you did this via `foreach ($inventory as $k => $v)` you'll find it much easier to manage. – Michael Berkowski Dec 28 '14 at 00:41
  • think of it this way - if you have to _"do a thing N times"_, use an incremental `for` loop. If you have to _"do a thing to each element in a collection"_, choose a `foreach` instead. – Michael Berkowski Dec 28 '14 at 00:43

3 Answers3

1

Your problem is that unsetting an element from an enumerated array will adjust the size of your array, but testing using sizeof() to see if you should exit your loop, so each iteration where you unset will reduce the number of values left to test.

$exclude = array('Dodge','Toyota');

$size = sizeof($inventory);
for($k=0; $size; $k++) {
    if(in_array(trim($inventory[$k]['car_name']), $exclude)) {
        unset($inventory[$k]);
    }
}

$inventory = array_values($inventory);
echo '<pre>';
print_r($inventory);
echo '</pre>';
Mark Baker
  • 209,507
  • 32
  • 346
  • 385
1

You are removing the index:value pair from the array, while iterating it. So after unsetting a value the index positions dont match or even exist.

Try copying the values you do need, into a new empty array like this:

$exclude = array('Dodge','Toyota');
$filtered = array();

for($k=0; $k<sizeof($inventory); $k++){
    if(in_array(trim($inventory[$k]['car_name']), $exclude)){
        // dont do this because it is changing the count of elements in the array unset($inventory[$k]);
    } else {
        $filtered[] = $inventory[$k]; // push the desired values into a new array
    }
}

echo '<pre>';
print_r($filtered);  // this should have the values that don't have 'Dodge' or 'Toyota'
echo '</pre>';

Edit: Mark's answer would be the best way to go cause it is also better performance wise

Juank
  • 6,096
  • 1
  • 28
  • 28
1

use foreach instead for($k=0; $k<sizeof($inventory); $k++):

foreach($inventory as $k => $row)

this is because while you are unsetting $inventory you skip elements

$k = 0, sizeof($inventory) = 12, you unset one of the items, $k++. $inventory[1] becomes $inventory[0]

$k = 1, sizeof($inventory) is now 11, you check $inventory[1] but not $inventory[0] (previous known as $inventory[1])

Peter
  • 16,453
  • 8
  • 51
  • 77