Undermine2k
Undermine2k

Reputation: 1491

PHP in_array does not check all cases

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>';



    ?>

Upvotes: 0

Views: 216

Answers (3)

Peter
Peter

Reputation: 16923

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])

Upvotes: 1

Juank
Juank

Reputation: 6196

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

Upvotes: 1

Mark Baker
Mark Baker

Reputation: 212412

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>';

Upvotes: 1

Related Questions