【发布时间】:2011-02-19 13:08:24
【问题描述】:
我想知道如何对对象数组进行array_intersect。
【问题讨论】:
-
你所说的“对象数组”是什么意思——你是指一个对象数组吗?
-
是的,就是对象数组。
我想知道如何对对象数组进行array_intersect。
【问题讨论】:
不错的 toString 函数已经实现并被称为 serialize ;) 所以
array_map(
'unserialize',
array_intersect(
array_map(
'serialize',
$obj1
),
array_map(
'serialize',
$obj2
)
)
);
将完成这项工作,上面提到的示例不起作用,因为 array_intersect 仅适用于有人提到的字符串
【讨论】:
仅出于完整性考虑:在您的对象中实现 __toString() 方法,返回一个唯一值。对于数据库实体,这可能就像返回带有记录 ID 后缀的完全限定类名一样简单。但它也可以通过做一些散列甚至更糟的事情来任意复杂。
在我看来,序列化自身或创建独特的东西来比较其对象是类的职责。使用类之外的任何东西来序列化一个对象可能会导致奇怪的行为(包括比较不同类的对象,这绝不会导致相等)。
【讨论】:
正确的解决方案是:
array_uintersect($arr1, $arr2, function ($a1, $a2) { return $a1 != $a2; });
注意回调函数中的 != 与@Artefacto 的答案相反。根据array_uintersect的文档,如果数组项相等,回调函数必须返回0(false)。
【讨论】:
你可以结合使用array_uintersect和spl_object_hash,看一个例子:
array_uintersect($a, $b, function($a, $b) {
return strcmp(spl_object_hash($a), spl_object_hash($b));
});
其中 '$a' 和 '$b' 是您想要相交的一些对象的数组。
【讨论】:
strcmp() 可以替换为 <=> 运算符,如下所示:return spl_object_hash($a) <=> spl_object_hash($b);
我使用array_udiff 为object array 实现array_intersect。
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" }
对于任何方案,您都可以拥有自己的差异函数。
【讨论】:
几天前遇到了类似的问题,虽然这些答案都在正确的道路上;我用它们来解决以下问题:
来自Artefacto的回答return $obj1 == $obj2并没有真正起作用,所以我写了一个简单的比较函数(基本上是获取序列化对象的md5并进行比较):
function object_compare($obj1, $obj2){
$md5 = function($obj){
return md5(serialize($obj));
};
return strcmp($md5($obj1), $md5($obj2));
}
那么只要用我们的比较函数调用array_uintersect就可以得到交集了:
# $array1 / $array2 are the array of objects we want to compare
return array_uintersect($array1, $array2, 'object_compare');
在我的例子中,我有一个未知/动态的对象数组,所以我更进一步,所以我不必特别声明 array_uintersect($array1, $array2, ...) - 但只需能够传入一个数组数组(对象):
# $multiarray_of_objects is our array of arrays
$multiarray_of_objects[] = 'object_compare';
return call_user_func_array('array_uintersect', $multiarray_of_objects);
只需记住将回调/比较函数的引用作为数组中的最后一个字符串传递。像魅力一样工作!
【讨论】:
return array_uintersect($array1, $array2, 'self::object_compare'); 应该可以工作,甚至是ClassName::object_compare,但是记住它需要是一个公共类函数。
检查两个对象是否相等的正确方法是使用==。因此:
array_uintersect($arr1, $arr2, function ($a1, $a2) { return $a1 == $a2; });
【讨论】:
array_intersect() 返回一个数组,其中包含所有参数中存在的 array1 的所有值。
那么在这个上下文中存在的含义(确切地说是这个函数),我在 php.net 上找到了我的答案:
如果你的对象没有实现到字符串的唯一转换,你就不能在对象数组上使用它。
【讨论】: