Laravel 5.7:基于多个键检测集合中的重复项(完成)但如何将重复项移动到另一个集合?

Posted

技术标签:

【中文标题】Laravel 5.7:基于多个键检测集合中的重复项(完成)但如何将重复项移动到另一个集合?【英文标题】:Laravel 5.7: Detecting duplicates in a collection based on multiple keys (done) but how to move dupes to another collection? 【发布时间】:2019-05-01 01:57:49 【问题描述】:

我有大量数据(数组项)。如果给定键的所有值都相同,则其中的每个项目都应区分为重复项。 把它想象成一个独特的复合键

$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)
];

在上面的示例中,唯一复合键是 uniqueunique2 的组合。

我能够消除欺骗。我是这样做的:

$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 可以为我完成这项工作,since the documentation is quite clear。

diff 方法将集合与另一个集合进行比较或 基于其值的普通 php 数组。该方法将返回 给定集合中不存在的原始集合中的值 收藏:

$dupes = $recordsAll->diff($recordsCleaned);
$dupes->all();

但是这不起作用。我也尝试了diffAssocdiffKeys。请帮帮我,我如何才能在全新的收藏中拥有第 4 个(被欺骗的)物品和所有下一个被欺骗的物品?

编辑:

我提出了以下解决方案,但从性能角度来看,我认为这并不好,因为生产集合将拥有几乎数百万个项目。

$recordsDupes = collect([]);
$recordsAll->each(function ($item) use ($recordsCleaned, $recordsDupes) 
    if ($recordsCleaned->contains($item) === false) 
        $recordsDupes->push($item);
    
);

【问题讨论】:

【参考方案1】:

当您在集合上使用diff 方法时,在多维情况下,您必须在集合内有集合。所以,你的代码应该是这样的:

$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' => 'baz', 'unique2' => 'zaz', 'whatever4' => 'whatever4'], // 4th DUPE (dupe of the 2nd because on both unique1 is bar and unique2 is zaz)
        ];
$recordsAll = collect($recordsAll);

$recordsCleaned = $recordsAll->unique(function ($item) 
    return $item['unique1'].$item['unique2'];
);


$recordsAll = collect($recordsAll->toArray())->map(function($row) 
                                            return collect($row);
                                    );
$recordsCleaned = collect($recordsCleaned->toArray())->map(function($row) 
                                        return collect($row);
                                    );

$diff = $recordsAll->diff($recordsCleaned);

在上面的代码变量$diff 将是一个集合,作为cleaned 和all 之间的区别。我已经对集合中的所有变量进行了操作,您可以根据需要将它们转换为数组。

如果有任何问题,我想你会理解上面的代码。

【讨论】:

哇,你的差异和我的完全一样,这意味着问题是我没有将集合$recordsAll$recordsCleaned 中的每个项目都包装为集合。现在好了。谢谢! @Matt 很高兴看到它对您有用。如果它确实帮助您解决问题,那么请通过接受此答案来关闭问题。 会做,会做! ? @Matt Cheers ;)

以上是关于Laravel 5.7:基于多个键检测集合中的重复项(完成)但如何将重复项移动到另一个集合?的主要内容,如果未能解决你的问题,请参考以下文章

忘记不修改原始集合 Laravel 5.7

markdown 在Laravel 5.7种子文件中截断具有外键约束的表。

如何在 Laravel 5.7 和 Laravel Collective 中使用动作 [重复]

laravel中的递归外键[重复]

从 Laravel 中的集合中获取键值

mysql 5.7 Group Replication