2010-12-03 20 views
5

Estoy buscando una forma concisa de comparar matrices de objetos en PHP. Sé que podría verificar las matrices de igual tamaño y luego recorrer una matriz buscando cada objeto en la segunda matriz, pero pensé que sería mejor usar una o más de las funciones de comparación de la matriz.Comparación de matrices de objetos

He probado un par de conjuntos de objetos y el principal problema Voy a subir contra es que las funciones de comparación gama insisten en que comparan elementos como strings, así:

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

salidas

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

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

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

)

Eso está bien si los objetos tienen métodos __toString() y si los __toString() los métodos devuelven un identificador único y nunca ''.

¿Pero qué sucede si ese no es el caso, por ejemplo de un objeto como éste:

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); 
    } 

} 

¿Es posible hacer array_uintersect($arr1,$arr2,$somecallback) que obliga al uso de Foo::Equals()? Por lo que puedo ver, la conversión a string ocurre antes de que se llame a la devolución de llamada.

¿Alguna idea de cómo evitar esto?

Respuesta

7

Sí, puede usar array_uintersect para esto.

un código de ejemplo:

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')); 
+0

Nice! Siempre me olvido de la notación 'array ('Fos', 'compare')' para indicar que la función de devolución de llamada pertenece a una clase. ¿Alguna idea de dónde está documentada esa notación? Solo me tropiezo con el ejemplo ocasional. – dnagirl

+1

@dnagirl: Vea el manual de PHP aquí: http://de.php.net/manual/en/language.pseudo-types.php#language.types.callback –

+0

@Stefan Gehrig: muchas gracias! A veces es muy difícil encontrar cosas cuando no sabes cómo se llaman. – dnagirl