PHP subset of 2 arrays containing objects - compared only by 1 attribute I'm looking for a fast way to get the subset of 2 arrays containing the same kind of objects using PHP functions.

I'm looking for the red part:



 

class Order
{
 private $_orderId;
 private $_someOtherAttributes;
}


I'm currently using array_uintersect() to get the intersection and array_udiff() to get rid of the intersection.

$array_1 = array($o1, $o2, $o3 ... $on);
$array_2 = array($o1, $o2, $o3 ... $on);

function order_hash($object) 
{
    return sprintf('%d', $object-&gt;getOrderId());
}

 function compare_objects($a, $b)
 {
      return strcmp(order_hash($a), order_hash($b));
 }

$intersection = array_uintersect($array_1, $array_2, 'compare_objects');
$subset = array_udiff($array_2, $intersection, 'compare_objects');


Is there a faster / more efficient way? I need to work with a lot of objects > 400 each array and very often as well.

I'm currently using PHP Version 7.1.4.



My changes: 

I changed the Order-Class to:

class Order
{
     public $_orderId;
     private $_someOtherAttributes;
}


and compare_objects() to:

function compare_objects($a, $b)
{
       if($a-&gt;_orderId&gt; $b-&gt;_orderId)
       {
           return 1;
       }
       else if($a-&gt;_orderId&lt; $b-&gt;_orderId)
       {
            return -1;
       }
       return 0;
}


and using array_udiff($array_1, $array_2, 'compare_objects') instead off array_udiff($array_2, array_udiff($array_1, $array_2, 'compare_objects'), 'compare_objects')

I'm aware that public attributes aren't the best practice, but changing it this way I gained 300% more speed.
As far as these things go, I think your performance is going to be close to ideal.  There is maybe a little room for improvement, namely:

I'm pretty sure all you need is array_udiff.  My suspicion (and some quick tests) suggest that this:

$subset = array_diff( $array_2, array_intersect( $array_1, $array_2 ) );


Is exactly equivalent to this:

$subset = array_diff( $array_2, $array_1 );


(some details excluded for brevity) So save yourself an expensive function call.  My only other suggestion would be a more "global" change that may or may not be helpful.  In your example it looks like you don't care about the keys.  In that case, use them.  When you build your array of objects use order_hash( $obj ) as the key.  They you can do array_diff on the array_keys, without having to worry about compare_objects method, i.e.:

$array1 = [
    order_hash( $o1 ) =&gt; $o1,
    order_hash( $o2 ) =&gt; $o2,
];

$array2 = [
    ... same thing ...
]

$keys_to_check = array_diff( array_keys( $array2, $array1 ) );
foreach ( $keys_to_check as $key )
    do_something( $array2[$key] );


It is a different way of organizing your data structures, and it takes a little more awareness about how your objects are stored.  However, if these arrays of objects are being passed back and forth frequently, and if you are frequently doing these kinds of comparisons, it can save you a lot of time (I think) because you only have to do your hash calculation once per object, instead of doing it once per object per intersect.

I frequently organize my structures this way (and do lots of diffs on them), and I find it easier to follow.  Basically, the thinking changes from:

Use this function to compare these arrays and see which ones are different

to

Check the keys of this array to see which ones are different

Personally I prefer the latter.