通过比较特定共享属性/列的值,保留两个对象数组中的相交对象
我正在寻找一种比较 PHP 中对象数组的简洁方法。我知道我可以只检查大小相等的数组,然后循环遍历一个数组,查找第二个数组中的每个对象,但我认为使用一个或多个数组比较函数会更好。
我已经测试了几个对象数组,我遇到的主要问题是数组比较函数坚持将元素作为字符串进行比较,如下所示:
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);
outputs
Array
(
[1] => Foo Object
(
[pk] => 2
)
[2] => Foo Object
(
[pk] => 3
)
[3] => Foo Object
(
[pk] => 4
)
)
如果对象具有__toString()
方法,并且如果这些 __toString()
方法返回唯一标识符并且从不返回 ''
。
但如果情况并非如此,会发生什么情况,比如对于这样的对象:
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);
}
}
是否可以执行 array_uintersect($arr1,$arr2,$somecallback) 来强制使用 Foo::等于()?据我所知,到 string
的转换发生在调用回调之前。
有什么想法可以解决这个问题吗?
I'm looking for a succinct way of comparing arrays of objects in PHP. I know I could just check for equal sized arrays and then loop through one array looking for each object in the second array, but I thought it would be nicer to use one or more of the array comparison functions.
I've tested a couple arrays of objects and the main problem I'm coming up against is that the array comparison functions insist on comparing elements as strings
, like this:
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);
outputs
Array
(
[1] => Foo Object
(
[pk] => 2
)
[2] => Foo Object
(
[pk] => 3
)
[3] => Foo Object
(
[pk] => 4
)
)
That's fine if the objects have __toString()
methods and if those __toString()
methods return a unique identifier and never ''
.
But what happens if that's not the case, say for an object like this:
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);
}
}
Is it possible to do array_uintersect($arr1,$arr2,$somecallback)
that forces the use of Foo::Equals()
? From what I can see the conversion to string
happens before the callback is called.
Any ideas how to get around this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,您可以使用 array_uintersect 来实现此目的。
一些示例代码:
Yes, you can use
array_uintersect
for this.Some example code:
@kapa 的答案的更现代的等价物可以使用具有箭头函数语法的匿名回调函数和用于返回 3 路比较整数的太空船运算符。 (演示)
The more modern equivalent of @kapa's answer can use an anonymous callback function with arrow function syntax and the spaceship operator for returning the 3-way comparison integer. (Demo)