Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing arrays of objects

Tags:

arrays

object

php

I'm looking for a succinct way of comparing arrays of objects in PHP. I know I could just check for equal sized arrays and then loop through one array looking for each object in the second array, but I thought it would be nicer to use one or more of the array comparison functions.

I've tested a couple arrays of objects and the main problem I'm coming up against is that the array comparison functions insist on comparing elements as strings, like this:

class Foo{
    public $pk=NULL;
    function __construct($pk){
        $this->pk=$pk;
    }

    function __toString(){
        return (string)$this->pk;//even an integer must be cast or array_intersect fails
    }
}

for($i=1;$i<7;$i++){
    $arr1[]=new Foo($i);
}
for($i=2;$i<5;$i++){
    $arr2[]=new Foo($i);
}

$int=array_intersect($arr1,$arr2);
print_r($int);

outputs

Array
(
[1] => Foo Object
    (
        [pk] => 2
    )

[2] => Foo Object
    (
        [pk] => 3
    )

[3] => Foo Object
    (
        [pk] => 4
    )

)

That's fine if the objects have __toString() methods and if those __toString() methods return a unique identifier and never ''.

But what happens if that's not the case, say for an object like this:

class Bar{
    public $pk=NULL;
    function __construct($pk){
        $this->pk=$pk;
    }

    function __toString(){
        return 'I like candy.';//same for all instances
    }

    function Equals(self $other){
        return ($this->pk==$other->pk);
    }

}

Is it possible to do array_uintersect($arr1,$arr2,$somecallback) that forces the use of Foo::Equals()? From what I can see the conversion to string happens before the callback is called.

Any ideas how to get around this?

like image 392
dnagirl Avatar asked Dec 03 '10 15:12

dnagirl


1 Answers

Yes, you can use array_uintersect for this.

Some example code:

class Fos {
    public $a = 0;
    function __construct($a) {
        $this->a = $a;
    }
    static function compare($a, $b) {
        if ($a->a == $b->a) return 0;
        if ($a->a > $b->a) return 1;
        if ($a->a < $b->a) return -1;
    }
}

$fos1 = array();
$fos2 = array();

for ($i = 1; $i < 10; $i++) {
    $fos1[] = new Fos($i);
}

for ($i = 8; $i < 18; $i++) {
    $fos2[] = new Fos($i);
}

$fosi = array_uintersect($fos1, $fos2, array('Fos','compare'));
like image 126
kapa Avatar answered Sep 30 '22 07:09

kapa