我有几个集合,我只想保留每个集合中存在的元素。
我检查了可用的方法,但没有找到任何匹配的方法。
$candidatesByConsultant = Consultant::find(request('consultant_id'))->candidates;
$candidatesByCreation = Candidate::whereBetween('created_at',[Carbon::parse(request('meeting_since')), Carbon::parse(request('meeting_to'))])->get();
你有什么想法吗? :)
intersect
方法可能合适:https://laravel.com/docs/5.8/collections#method-intersect
取自文档的示例:
$collection = collect(['Desk', 'Sofa', 'Chair']);
$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);
$intersect->all();
// [0 => 'Desk', 2 => 'Chair']
但是,特别是如果您尝试交叉多个 Eloquent 模型 集合,它可能不起作用,因为两个模型之间的相等性是由 Model::is() 方法定义的。查看 https://laravel.com/docs/5.8/eloquent#comparing-models 有关比较两个 Eloquent 模型的更多信息。
为了处理这个问题,我会执行以下操作,假设模型的主键是
id
:
$candidatesByConsultant = Consultant::find(request('consultant_id'))->candidates;
$candidatesByCreation = Candidate::whereBetween('created_at',[Carbon::parse(request('meeting_since')), Carbon::parse(request('meeting_to'))])->get();
$candidates = $candidatesByConsultant->merge($candidatesByCreation)->unique("id");
内置的功能是
$collection->intersect($other)
,但您也可以使用简单的自定义过滤器来实现所需的结果:
$left = collect([Model::find(1), Model::find(2), Model::find(3)]);
$right = collect([Model::find(1), Model::find(3), Model::find(5)]);
$result = $left->filter(function ($value, $key) use ($right) {
return $right->contains(function ($v, $k) use ($value) {
return $v->id === $value->id;
});
});
这将通过
id
执行模型比较。但它的性能不是很好。另一种方法是检索两个 ids
数组,将它们相交并根据此列表过滤合并的集合:
$left = collect([Model::find(1), Model::find(2), Model::find(3)]);
$right = collect([Model::find(1), Model::find(3), Model::find(5)]);
$merged = $left->merge($right);
$ids = array_intersect($left->pluck('id')->toArray(), $right->pluck('id')->toArray());
$result = $merged->filter(function ($value, $key) use ($ids) {
return in_array($value->id, $ids);
});