如何查找重复项并保留以后的条目

Posted

技术标签:

【中文标题】如何查找重复项并保留以后的条目【英文标题】:How to find duplicates and preserve the later entry 【发布时间】:2021-09-19 18:34:27 【问题描述】:

我有两个来自不同来源的对象列表,如下所示:

public class PersonToolDto 
   public int PersonId  get; set; 

   public int ToolId  get; set; 

   public DateTime CreatedAt  get; set; 


var personToolListFromSomeSource = new List<PersonToolDto>
     new PersonTool1, 1, 2021-07-07,
     new PersonTool2, 1, 2021-07-07,
     new PersonTool3, 1, 2021-07-07,


var personToolListFromAnotherSource = new List<PersonToolDto>
     new PersonTool1, 1, 2021-06-07,
     new PersonTool2, 1, 2021-07-07,
     new PersonTool3, 1, 2021-07-07,


我想消除重复项,只保留最新条目。使用 linq 或其他方法来实现这一目标的简单快速的方法是什么?一个人的简单 groupby by id 不会消除重复,我有点迷失如何比较日期。

我想保留结构并继续使用列表。

【问题讨论】:

【参考方案1】:

您可以执行以下操作:

var withoutDuplicates = personToolListFromSomeSource
    .Concat(personToolListFromAnotherSource)
    .GroupBy(p => new  p.PersonId, p.ToolId )
    .Select(g => g.OrderByDescending(x => x.CreatedAt).First())
    .ToList();

【讨论】:

也可以使用GroupBy重载来消除选择:.GroupBy(p =&gt; new p.PersonId, p.ToolId , (k,v)=&gt;v.OrderByDescending(x =&gt; x.CreatedAt).First()) 另外,看起来 OP 只希望通过 PersonId 区分,而不是 PersonId 和 ToolId【参考方案2】:

对于即将推出的 .NET 6,您还可以使用新的DistinctBy

var output = personToolListFromSomeSource
    .Concat(personToolListFromAnotherSource)
    .OrderByDescending(x => x.CreatedAt)
    .DistinctBy(x => x.PersonId)
    .ToList(); 

.NET 6 也有一个MaxBy,所以另一种选择是:

var output = personToolListFromSomeSource
    .Concat(personToolListFromAnotherSource)
    .GroupBy(x => x.PersonId, (k,v) => v.MaxBy(x => x.CreatedAt))    
    .ToList();

【讨论】:

以上是关于如何查找重复项并保留以后的条目的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL:如何将大写/小写视为重复项,而不是更改大小写并保留较早的条目?

MongoDB 使用 ensureIndex 删除重复项,但保留最后一个条目而不是第一个条目

SQL SERVER 2005删除重复数据

删除一张表中重复数据并保留一条ID最小的记录

删除重复项,保留具有最大绝对值的条目

Java 8 Streams 减少删除重复项,保留最新条目