Obtener la diferencia de dos matrices de objetos

4 minutos de lectura

avatar de usuario de roflwaffle
waffle

se que hay array_diff y array_udiff para comparar la diferencia entre dos matrices, pero ¿cómo lo haría con dos matrices de objetos?

array(4) {
    [0]=>
        object(stdClass)#32 (9) {
            ["id"]=>
            string(3) "205"
            ["day_id"]=>
            string(2) "12"
        }
}

Mis arreglos son como este, estoy interesado en ver la diferencia de dos arreglos basados ​​en id valores de columna.

Avatar de usuario de Jordan Running
jordan corriendo

Esto es exactamente lo que array_udiff es para. Escribe una función que compare dos objetos de la manera que te gustaría, luego di array_udiff para usar esa función. Algo como esto:

function compare_objects($obj_a, $obj_b) {
  return $obj_a->id - $obj_b->id;
}

$diff = array_udiff($first_array, $second_array, 'compare_objects');

O, si está usando PHP> = 5.3, puede usar un función anónima en lugar de declarar una función:

$diff = array_udiff($first_array, $second_array,
  function ($obj_a, $obj_b) {
    return $obj_a->id - $obj_b->id;
  }
);

  • Su función de comparación no funcionará, una solución rápida sería cambiar el == a -.

    – Salathe

    24 de junio de 2011 a las 18:56

  • Tienes razón, salathe. Fijado.

    – Jordán corriendo

    24 de junio de 2011 a las 19:05

  • gracias, era el - eso me estaba echando para atrás.

    – waffle

    25 de junio de 2011 a las 0:04

  • Nota: en comparar_objetos, puede devolver 0 para indicar que los objetos son iguales. y -1 para decir que son diferentes.

    –Francisco Corrales Morales

    11 de marzo de 2015 a las 17:29

  • Las funciones internas de esta función parecen usar cierta clasificación, por lo que realmente debe devolver -1 o 1 cuando los objetos no son iguales, por lo que el comentario de @FranciscoCorralesMorales no es correcto.

    – fietserwin

    7 de junio de 2018 a las 8:16

Aquí hay otra opción, si desea ejecutar la diferencia de acuerdo con el objeto instancias. Usaría esto como su devolución de llamada a array_udiff:

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

Solo querría usar eso si está seguro de que las matrices contienen solo objetos: aquí está mi caso de uso personal.

  • y que hay con return $a === $b ? 0 : -1 ? ¿No haría lo mismo al comparar variables de objetos que apuntan a la misma instancia de objeto?

    – Dimitri K.

    7 abr 2017 a las 10:39


  • Las funciones internas de esta función parecen usar cierta clasificación, por lo que realmente debe devolver -1 o 1 cuando los objetos no son iguales, por lo que el comentario de @Dimitry K no es correcto.

    – fietserwin

    7 de junio de 2018 a las 8:17

Y aquí hay otra opción si desea comparar las propiedades de las cadenas (por ejemplo, el nombre):

$diff = array_udiff($first_array, $second_array,
  function ($obj_a, $obj_b) {
    return strcmp($obj_a->name, $obj_b->name);
  }
);

Avatar de usuario de Aditya
Aditya

Aquí está mi opinión sobre esto

/**
     * Compare two objects (active record models) and return the difference. It wil skip ID from both objects as 
     * it will be obviously different
     * Note: make sure that the attributes of the first object are present in the second object, otherwise
     * this routine will give exception.
     * 
     * @param object $object1
     * @param object $object2
     * 
     * @return array difference array in key-value pair, empty array if there is no difference
     */
    public static function compareTwoObjects($object1, $object2)
    {
        $differences=[];
        foreach($object1->attributes as $key => $value) {
            if($key =='id'){
                continue;
            }
            if($object1->$key != $object2->$key){
                $differences[$key] = array(
                                            'old' => $object1->$key,
                                            'new' => $object2->$key
                                        );
            }
        }
        return $differences;
    }

Tiene dos matrices que contienen objetos, usando array_udiff() es ciertamente apropiado para esta tarea.

Demostraré esta técnica con sintaxis moderna (“operador de nave espacial” y “sintaxis de función de flecha”).

Considere este conjunto de datos de muestra:

$array1 = [
    (object) ['id' => '204', 'day_id' => '12'],
    (object) ['id' => '205', 'day_id' => '13'],
    (object) ['id' => '206', 'day_id' => '14'],
    (object) ['id' => '207', 'day_id' => '15'],
];
$array2 = [
    (object) ['id' => '203', 'day_id' => '11'],
    (object) ['id' => '205', 'day_id' => '13'],
    (object) ['id' => '207', 'day_id' => '14'],
    (object) ['id' => '209', 'day_id' => '17'],
];

Los datos devueltos de array_udiff() serán las filas de la primera matriz que no coinciden en la segunda matriz.

Código: (Manifestación)

var_export(
    array_udiff(
        $array1,
        $array2,
        fn($a, $b) => $a->id <=> $b->id
    )
);

devuelve estas dos filas:

[
    (object) ['id' => '204', 'day_id' => '12'],
    (object) ['id' => '206', 'day_id' => '14'],
]

Invirtiendo el orden de los dos primeros parámetros: (Manifestación)

[
    (object) ['id' => '203', 'day_id' => '11'],
    (object) ['id' => '209', 'day_id' => '17'],
)

¿Ha sido útil esta solución?