Linq比较两个不同的列表并选择外部联接

本文关键字:列表 选择 外部 比较 两个 Linq | 更新日期: 2023-09-27 17:58:22

我有两个不同的类,代表两种类型的数据。第一种是未存储的原始格式。第二种是张贴的格式。

 public class SalesRecords
 {
    public long? RecordId { get; set; }
    public DateTime RecordDate { get; set; }
    public string RecordDesc { get; set; }
    // Other non-related properties and methods
 }
 public class PostedSalesRecords
 {
      public long? CorrelationId { get; set; }
      public DateTime RecordDate { get; set; }
      public DateTime? PostedDate { get; set; }
      public string RecordDesc { get; set; }
      // Other non-related properties and methods
 }

我们的系统有一个销售记录列表。这些销售记录在用户确定的时间发布到不同的系统。我正在创建一个屏幕,显示所有已发布的销售记录以及未发布的销售纪录,作为对账。我的网格的数据源将是PostedSalesRecords的列表。我需要做的是找出List<SalesRecords>中哪些记录不在List<PostedSalesRecords>中,然后将那些未存储的SalesRecords映射到PostedSalesRecords。我很难找到快速比较的方法。基本上我试过了,但速度非常慢:

 private List<SalesRecords> GetUnpostedSalesRecords(
      List<SalesRecords> allSalesRecords,
      List<PostedSalesRecords> postedSalesRecords)
 {
      return allSalesRecords.Where(x => !(postedSalesRecords.Select(y => y.CorrelationId.Value).Contains(x.RecordId.Value))).ToList();
 }

我最大的问题是我过滤了很多数据。我将大约55000个总销售记录与大约17000个已发布记录进行比较。我处理这个大约需要2分钟。有什么可能加快速度的方法吗?谢谢

Linq比较两个不同的列表并选择外部联接

您可以尝试外部联接,请查看这是否有助于提高性能:

 var test = (from s in allSalesRecords
                join p in postedSalesRecords on s.RecordId equals p.CorrelationId into joined
                from j in joined.DefaultIfEmpty()
                where j == null
                select s).ToList();

或者,在您的实现中,您可以为postedSalesRecords创建一个仅包含Id的字典,然后在查询中使用该集合,这肯定有助于提高性能,因为查找时间将是O(1),而不是遍历每个记录的整个集合。

 var postedIds = postedSalesRecords.Select(y => y.CorrelationId.Value)
                                      .Distinct().ToDictionary(d=>d);
return allSalesRecords.Where(x => !(postedIds.ContainsKey(x.RecordId.Value))).ToList();

使用MSDN上描述的左外部联接应该更有效:

private List<SalesRecords> GetUnpostedSalesRecords(
    List<SalesRecords> allSalesRecords,
    List<PostedSalesRecords> postedSalesRecords)
{
    return (from x in allSalesRecords
            join y in postedSalesRecords on x.RecordId.Value
                                     equals y.CorrelationId.Value into joined
            from z in joined.DefaultIfEmpty()
            where z == null
            select x).ToList();
}

这可能会通过散列集来实现。您可以自己实现这一点(可以说这样做更清楚):在一个或两个列表中构建ID值的HashSet<long>,以确保每次遍历外部列表时不需要重复的O(N)查找。