我似乎无法弄清楚PHP幕后正在发生什么魔术,为什么array_unique无法检测到我的重复数据。
在我的特定情况下,我有2个用户集合,我将这些集合合并为一个集合,然后仅保留唯一的条目。为此,我将两个集合都转换为数组,对其进行array_merge()
编码,然后根据参数应用array_unique(..., SORT_REGULAR)
,以便将它们作为对象进行比较,而无需进行任何转换。我意识到比较对象是一个滑坡,但是在这种情况下,它比我要怪。
合并之后但在唯一性检查之前,我有以下状态:
如您所见,项目4和11是相同的用户实体(非严格和严格比较都同意这一点)。但是在array_unique()
之后,由于某种原因,它们都保留在列表中:
如您所见,检测到并删除了项目7-10,但没有检测到项目11。
那怎么可能?我在这里没看到什么?
当前正在运行PHP 7.4.5
代码来自使用Symfony 4.4.7和Doctrine ORM 2.7.2的项目(尽管我认为这应该无关紧要,如果==
和===
比较对象相等)。
奖励积分的有趣事实-连续两次应用array_unique
会产生实际上唯一的结果:
头脑=吹牛
更新:我已在throw new \RuntimeException()
方法中添加了User::__toString()
,以确保没有人进行字符串转换。
请不要建议转换为字符串-这既不是我的问题的解决方案,也不是这个问题的内容。
最佳答案
对于您眼前的问题,我真的怀疑这是由于
使用array_unique
标志时,SORT_REGULAR
通过以下方法从数组中删除元素:
并且因为您在
Proxy
集合的中间确实有一个User
对象,所以这可能会导致您当前面临的问题。正如
sort
page of PHP documentation指出的那样,这似乎得到Marvin's comment警告的支持。Warning Be careful when sorting arrays with mixed types values because
sort()
can produce unexpected results, ifsort_flags
isSORT_REGULAR
.
资料来源:https://www.php.net/manual/en/function.sort.php#refsect1-function.sort-notes
现在为可能的解决方案,这可能会给您带来一些Symfony的味道。
它使用
ArrayCollection
filter
和 contains
方法来过滤第二个集合,并仅添加第一个集合中不存在的元素。为了完全完成,此解决方案还利用了
use
language construct,以便将第二个ArrayCollection
传递给filter
所需的闭包函数。这将导致一个不包含重复用户的新
ArrayCollection
。public static function merge(Collection $a, Collection $b, bool $unique = false): Collection {
if($unique){
return new ArrayCollection(
array_merge(
$a->toArray(),
$b->filter(function($item) use ($a){
return !$a->contains($item);
})->toArray()
)
);
}
return new ArrayCollection(array_merge($a->toArray(), $b->toArray()));
}
关于php - 为什么array_unique不检测重复的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61910894/