获取两个对象数组的差异

40

我知道有array_diffarray_udiff用于比较两个数组之间的差异,但如果是两个对象数组,我该怎么做呢?

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

我的数组就像这个,我想看到基于id列值的两个数组的差异。

5个回答

88

这正是array_udiff的用法。写一个函数来按照你想要的方式比较两个对象,然后告诉array_udiff使用该函数。类似于这样:

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

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

或者,如果您使用的是 PHP >= 5.3 版本,则可以使用匿名函数来替代声明函数:

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

你的比较函数不起作用,一个快速的解决方法是将 == 改为 - - salathe
1
没错,salathe。修复了。 - Jordan Running
谢谢,正是那个“-”让我困扰了一下。 - roflwaffle
5
注意:在 compare_objects 函数中,你可以返回 0 来表示对象相等,返回 -1 来表示它们不同。 - Francisco Corrales Morales
这个函数的内部似乎使用了一些排序,因此当对象不相等时,你确实必须返回-1或1,所以@FranciscoCorralesMorales的评论是不正确的。 - fietserwin
注意:您可以使用 PHP 7.4 中的太空船运算符(<=>)代替“-”。 - Yann Chabot

7

如果您想根据对象实例运行差异,则有另一种选择。您可以使用以下内容作为array_udiff的回调函数:

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

只有在确定两个数组都只包含对象时,才需要使用它 - 这是我的个人用例


return $a === $b ? 0 : -1 是什么情况?如果比较指向同一对象实例的对象变量,它不会做相同的事情吗? - Dimitry K
3
这个函数的内部似乎使用了一些排序,所以当对象不相等时,你必须返回-1或1,因此Dimitry K的评论是不正确的。 - fietserwin

6

如果您想比较字符串属性(例如名称),这里还有另一个选择:

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

0
这是我的看法
/**
     * 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;
    }

0

您有两个包含对象的数组 -- 使用 array_udiff() 函数绝对是这个任务所需的。

我将使用现代语法("spaceship operator" 和 "arrow function syntax")演示这种技术。

考虑以下示例数据集:

$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'],
];
< p > array_udiff() 返回的数据将是第一个数组中未在第二个数组中匹配的行。

代码:(演示

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

返回这两行:

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

将前两个参数的顺序颠倒:(演示)

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接