feub
feub

Reputation: 589

Remove objects from an array of objects if a property value is found in another flat array

I have 2 PHP arrays, a simple one:

array
  0 => int 5
  1 => int 6

and an array of objects:

array
  0 => 
    object(stdClass)[43]
      public 'id' => int 1
  1 => 
    object(stdClass)[46]
      public 'id' => int 3
  2 => 
    object(stdClass)[43]
      public 'id' => int 5
  3 => 
    object(stdClass)[46]
      public 'id' => int 6
  4 => 
    object(stdClass)[46]
      public 'id' => int 7

I'd like to make a diff of these 2 arrays to eliminate in the second those present in the first. In this example, I don't want the ids 5 and 6 in the second array.

Upvotes: 2

Views: 11784

Answers (5)

mickmackusa
mickmackusa

Reputation: 47884

PHP has a native function to handle this filtration task without any special data preparation. In the callback, it will be unknown if the $a or $b value will come from the first or second array. For this reason, first check if the variable is the object with an id property, if so use that, otherwise, use the non-object value. Demo

$blacklist = [5, 6];
$objects = [
    (object)["id" => 1],
    (object)["id" => 3],
    (object)["id" => 5],
    (object)["id" => 6],
    (object)["id" => 7]
];

var_export(
    array_udiff(
        $objects,
        $blacklist,
        fn($a, $b) => ($a->id ?? $a) <=> ($b->id ?? $b)
    )
);

Output:

array (
  0 => 
  (object) array(
     'id' => 1,
  ),
  1 => 
  (object) array(
     'id' => 3,
  ),
  4 => 
  (object) array(
     'id' => 7,
  ),
)

Upvotes: 0

Nick Maroulis
Nick Maroulis

Reputation: 487

For versions older than 5.3

 foreach( $arr_2nd as $key => $val  )
{
   $arr_2nd[$key] = $val->id;
}

array_diff( $arr_1st, $arr_2nd );

Upvotes: 1

Glitch Desire
Glitch Desire

Reputation: 15023

Assuming $objects is your array of objects, and $values is your array of values to remove...

You could use a foreach loop if you want to return objects:

$values = array(5, 6);
$objects = array(
    (object) array("id" => 1),
    (object) array("id" => 3),
    (object) array("id" => 5),
    (object) array("id" => 6),
    (object) array("id" => 7)
);
foreach($objects as $key => $object) {
    if(in_array($object->id,$values)) {
        unset($objects[$key]);
    }
}

Live demo (0.008 sec)

If you want to use the diff function itself (that's possible but awkward, less readable and will just return an array of values) you can (as Baba suggested) return the id of the object inline:

$values = array(5, 6);
$objects = array(
    (object) array("id" => 1),
    (object) array("id" => 3),
    (object) array("id" => 5),
    (object) array("id" => 6),
    (object) array("id" => 7)
);
$diff = array_diff(array_map(function ($object) {
    return $object->id;
}, $objects), $values);

Live demo (0.008 sec)

Upvotes: 3

Baba
Baba

Reputation: 95101

You can try :

$diff = array_diff(array_map(function ($v) {
    return $v->id;
}, $array2), $array1);

See Live DEMO

Upvotes: 3

fullybaked
fullybaked

Reputation: 4127

Loop over the second array and use in_array method to check for existing values in first

$firstArray = array(5, 6);
foreach ($objects as $key => $object) {
    if (in_array($object->id, $firstArray)) {
        unset($objects[$key];
    }
}

Upvotes: 2

Related Questions