У меня огромная коллекция данных (элементы массива).Каждый элемент должен различаться как дублирующий, если все значения для заданных ключей одинаковы. Представьте это как уникальный составной ключ .
$recordsAll = [
['unique1' => 'foo', 'unique2' => 'bar', 'whatever1' => 'whatever1'], // 1st OK
['unique1' => 'baz', 'unique2' => 'zaz', 'whatever2' => 'whatever2'], // 2nd OK
['unique1' => 'foo', 'unique2' => 'kkk', 'whatever3' => 'whatever3'], // 3rd OK (because unique2 is kkk not bar)
['unique1' => 'bar', 'unique2' => 'zaz', 'whatever4' => 'whatever4'], // 4th DUPE (dupe of the 2nd because on both unique1 is bar and unique2 is zaz)
];
В приведенном выше примере уникальный составной ключ представляет собой комбинацию unique
и unique2
.
IЯ могу удалить обманщиков.Я делаю это так:
$recordsAll = collect($recordsAll);
$recordsCleaned = $recordsAll->unique(function ($item) {
return $item['unique1'].$item['unique2'];
});
Я могу подтвердить, что это работает, подсчитав результаты в обоих.Сбор со всем должен дать мне явно 4
, в то время как очищенный должен дать мне 3
, и они делают ...
dd($recordsAll->count(), $recordsCleaned->count()); // prints 4 and 3
Что я не знаю, как сделать (или, по крайней мере, у меня есть)идея, но она не работает), состоит в том, чтобы сохранить дублированные записи в другом массиве (коллекции).Так что я не хочу только удалять дупы и использовать очищенную коллекцию.Позже я также хочу выполнить некоторую логику для коллекции, содержащей дубликаты.
Я думал, что простой diff
сделает работу за меня, , так как документация вполне понятна .
Метод diff сравнивает коллекцию с другой коллекцией или простым массивом PHP на основе ее значений.Этот метод возвращает значения в исходной коллекции, которых нет в данной коллекции:
$dupes = $recordsAll->diff($recordsCleaned);
$dupes->all();
Однако это не работает.Я тоже пробовал с diffAssoc
и diffKeys
.Пожалуйста, помогите мне, как я могу иметь 4-й (дублированный) элемент и все следующие дубликаты в совершенно новой коллекции?
edit:
Я придумал решение нижеНо я не думаю, что это хорошо с точки зрения производительности, поскольку в производственной коллекции будет почти миллионы предметов.
$recordsDupes = collect([]);
$recordsAll->each(function ($item) use ($recordsCleaned, $recordsDupes) {
if ($recordsCleaned->contains($item) === false) {
$recordsDupes->push($item);
}
});