Объедините 2 коллекции (сохраните похожие) - PullRequest
0 голосов
/ 29 мая 2019

У меня есть несколько коллекций, я хочу сохранить только элементы, присутствующие в каждой коллекции.

Я просмотрел доступные методы, но не нашел ничего подходящего.

$candidatesByConsultant = Consultant::find(request('consultant_id'))->candidates;
$candidatesByCreation = Candidate::whereBetween('created_at',[Carbon::parse(request('meeting_since')), Carbon::parse(request('meeting_to'))])->get();

Есть идеи?:)

Ответы [ 3 ]

2 голосов
/ 29 мая 2019

Чтобы иметь значения, которые присутствуют только в обеих коллекциях, вы должны использовать метод пересечения:

$result = $candidatesByConsultant->intersect($candidatesByCreation);

Метод пересечения пересекает значения обеих коллекций. Вы можете прочитать его в официальной документации Laravel .

И чтобы получить результаты, которых нет в обеих коллекциях, вы должны использовать метод diff:

$result = $candidatesByConsultant->diff($candidatesByCreation);

Метод diff находит различия между коллекциями. Вы можете прочитать его в официальной документации Laravel .

0 голосов
/ 29 мая 2019

Встроено для этого $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);
});
0 голосов
/ 29 мая 2019

Может подойти 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");

Вы можете проверить документацию merge () и unique () .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...