我有两个不同的类,代表两种类型的数据。第一种是未存储的原始格式。第二种是张贴的格式。
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分钟。有什么可能加快速度的方法吗?谢谢
您可以尝试外部联接,请查看这是否有助于提高性能:
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)查找。