2010-05-14 13 views

Respuesta

2

array_intersect() devuelve una matriz que contiene todos los valores de array1 que están presentes en todos los argumentos.

Entonces, ¿qué quiere decir presente en este contexto (exacly esta función), i conocer en php.net mi respuesta:

Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same.

entonces no se puede utilizar en gran variedad de objetos si tus objetos no implementan la conversión única en cadena.

+4

Eso es incorrecto. Hay al menos tres formas en que los objetos se pueden convertir en una cadena. Pueden ser una clase PHP e implementar __toString, pueden tener un manejador de conversión que acepta IS_STRING y pueden tener un manejador get que devuelve un zval que se puede convertir a una cadena. – Artefacto

+0

+1 @Artefacto, envíe una respuesta con un ejemplo utilizando objetos arbitrarios y array_intersección(). – Dolph

+0

Si sus objetos no implementan una conversión única a cadena. – Svisstack

1

La forma correcta de comprobar si dos objetos son iguales es usar ==. Por lo tanto:

array_uintersect($arr1, $arr2, function ($a1, $a2) { return $a1 == $a2; }); 
+0

esto no funciona .. u tiene alguna otra codificación? –

+1

Tendrás que ser más específico. ¿Qué no funciona? ¿Hay algún mensaje de error? ¿Qué mensaje de error? La salida no es la esperada? ¿Qué se esperaba? ¿Qué obtuviste? – Artefacto

+1

Esto no funciona porque array_unintersect necesita la función de comparación para devolver 1, -1 o 0. Consulte aquí para obtener una explicación completa y un ejemplo http://php.net/manual/en/function.array-uintersect. php # 72841 – Tim

6

agradable toString función ya está implementado y se llama serializar;) así que

array_map(
    'unserialize', 
    array_intersect(
     array_map(
      'serialize', 
      $obj1 
     ), 
     array_map(
      'serialize', 
      $obj2 
     ) 
    ) 
); 

va a hacer el trabajo, el ejemplo mencionado más alta no funcionan porque array_intersect trabajo de únicamente con cadenas como alguien mencionado también

+0

excelente hack. funciona perfectamente :) – yitwail

+0

en un pensamiento posterior, esto no es adecuado si los objetos tienen métodos. cuando serializas, pierdes los métodos, por lo que solo se conservan las propiedades – yitwail

2

Tuve un problema similar hace unos días, mientras que estas son las respuestas están en el camino correcto; Los he usado para trabajar el siguiente:

De la respuesta de Artefacto return $obj1 == $obj2 no funcionaba, así que escribí una función comparativa sencilla (básicamente obtiene el MD5 del objeto serializado y lo compara eso):

function object_compare($obj1, $obj2){ 
    $md5 = function($obj){ 
    return md5(serialize($obj)); 
    }; 
    return strcmp($md5($obj1), $md5($obj2)); 
} 

Entonces Jut una cuestión de llamar array_uintersect con nuestra función comparativa para obtener la intersección:

# $array1/$array2 are the array of objects we want to compare 
return array_uintersect($array1, $array2, 'object_compare'); 

En mi caso, tuve una matriz desconocida/dinámica de los objetos, así que lo llevó un paso más allá, así que don' tengo que declarar array_uintersect($array1, $array2, ...) específicamente -, pero sólo ser capaz de pasar de una matriz de matrices (de objetos):

# $multiarray_of_objects is our array of arrays 
$multiarray_of_objects[] = 'object_compare'; 
return call_user_func_array('array_uintersect', $multiarray_of_objects); 

Sólo tengo que recordar a pasar en la referencia a nuestra devolución de llamada/función comparativa como la última cadena de la matriz. ¡Funciona de maravilla!

+0

Debido a que trabajas dentro de una clase de controlador, no podría hacerlo así, pero usar tu enfoque con el formato de Artefacto funcionaba como un hechizo. – Magnanimity

+0

En una clase 'return array_uintersect ($ array1, $ array2, 'self :: object_compare');' debería funcionar, o incluso 'ClassName :: object_compare', pero recuerde que necesita ser una función de clase pública. – Atari

0

Utilizo array_udiff para implementar array_intersect para un object array.

function diff($a, $b) { 
if($a === $b) { 
    return 0; 
} else { 
    return 1;} 
} 

$array_1 = array('a', 'b', 'c');  

$array_2 = array('c', 'd','e');  

$array = array_udiff($array_1, array_udiff($array_1, $array_2, 'diff'),'diff'); 

var_dump($array); 
return array(1) { [2]=> string(1) "c" } 

Puede tener su propia función de diferencia para cualquier esquema.

8

Usted puede utilizar en conjunción con array_uintersect spl_object_hash, ver un ejemplo:

array_uintersect($a, $b, function($a, $b) { 
     return strcmp(spl_object_hash($a), spl_object_hash($b)); 
    }); 

donde '$ a' y 'b $' son matrices de algunos objetos que desee para cruzarse.

+0

Buena solución. Para lectores contemporáneos: en php7, el 'strcmp()' puede ser reemplazado por el operador '<=>', así: 'return spl_object_hash ($ a) <=> spl_object_hash ($ b);' –

-1

La solución correcta sería:

array_uintersect($arr1, $arr2, function ($a1, $a2) { return $a1 != $a2; }); 

Nota del = en la función de devolución de llamada en contraposición a la respuesta de @Artefacto!. Según la documentación de array_uintersect, la función de devolución de llamada debe devolver 0 (falso) si los elementos de la matriz son iguales.

+0

Esto es un hack de tipo innecesario, el La función de devolución de llamada debe devolver un entero (-1, 0, 1) si el primer valor es menor que, igual o mayor que el segundo, como para las funciones de clasificación. El tipo de transmisión implícita de falso a 0 confundirá a los lectores de su código. – amik

0

Para completar: Implemente el método __toString() en su objeto devolviendo un valor único. Para las entidades de base de datos, esto podría ser tan fácil como devolver el nombre de clase totalmente calificado postfijo con el ID del registro. Pero también puede ser arbitrariamente complejo haciendo algo de hash o incluso cosas peores.

En mi opinión, es el deber de la clase serializarse o crear algo único para comparar sus objetos. El uso de cualquier elemento fuera de una clase para serializar un objeto puede provocar un comportamiento extraño (incluida la comparación de objetos de diferentes clases, que nunca deben dar como resultado la igualdad).

Cuestiones relacionadas