如何解决C# foreach 循环和匹配有没有更快的方法来做到这一点?
我需要将一个列表中的值匹配到另一个列表。
两者都是列表。两者都有数十万条记录。
希望有人能告诉我一种方法来使这个更快一点,因为它需要很长时间才能匹配。
foreach (var item in availabilityItems)
{
foreach (var page in from page in pricePagelist
where item.Number == page.vendorItemNo
where item.StartDate == page.SubSeasonStartDate
where item.EndDate == page.SubSeasonEndDate
select page)
{
item.vendorItemNo = page.vendorItemNo;
item.PricePageNo = page.PricePageNo;
item.NaItemNo = page.ItemNo;
}
}
解决方法
如果它可以全部放入内存,您可以使用 Dictionary
来存储项目以便快速查找。根据您的数据库,这将减少您的数据库负载,消除对数据库端的索引和排序的需要,尤其是在您必须频繁运行此过程的情况下。
代码可能更容易理解,虽然阅读两个排序列表的另一个答案很聪明,但它可能需要更复杂的代码,并且还强制数据库执行 order by,使用索引和额外的 IO。
显然,如果您有超过 1000 万条记录,这会开始崩溃,但在该记录范围内应该没问题。
Dictionary<string,PageItem> lookup = new Dictionary<string,PageItem>(StringComparer.OrdinalIgnoreCase);
批量加载示例
foreach (var item in pricePageList)
{
lookup[item.VendorItemNo + "|" + item.SubSeasonStartDate + "|" + item.SubSeasonEndDate] = item;
}
示例搜索:
foreach (var item in availabilityItems)
{
string key = item.Number + "|" + item.SubSeasonStartDate + "|" + item.SubSeasonEndDate;
if (lookup.TryGetValue(key,out PageItem match))
{
item.Number = match.VendorItemNo;
item.PricePageNo = match.PricePageNo;
item.NaItemNo = match.ItemNo;
}
}
,
这是一种防止多次列表扫描的简单算法。
如果两个列表都在 Number/VendorItemNo
上排序,您可以使用 2 个索引变量自上而下扫描并将 Number
与 VendorItemNo
进行比较。如果 left
较大,则增加 right
的索引。否则,如果 right
更高,则增加左侧的索引。如果它们相等,则您匹配并增加两个索引。这背后的整个想法是您只需一次浏览每个列表。它也可以用于多个列表。
例如两个按 id 排序的列表。
使用索引扫描它们:
1234 <- 1233 <-
1236 1234
1237 1235
1238 1238
比较一下,左边比右边高,右边增加。
1234 <- 1233
1236 1234 <-
1237 1235
1238 1238
我们有一场比赛。 (当然你有一些额外的标准需要检查......)同时增加
1234 1233
1236 <- 1234
1237 1235 <-
1238 1238
左边高,右边增加
1234 1233
1236 <- 1234
1237 1235
1238 1238 <-
现在右边更高,所以向左增加
1234 1233
1236 1234
1237 <- 1235
1238 1238 <-
右边还高,再增加左边。
1234 1233
1236 1234
1237 1235
1238 <- 1238 <-
我们匹配了...所以只有 1234 和 1238 匹配。
如果一个超过列表的数量,你就完成了。
,假设 pricePageList
包含关于三个字段组合的唯一元素,您可以构造一个包含页面的 Dictionary<TKey,Page>
,使用 ValueTuple<int,DateTime,DateTime>
作为键。这种类型是开箱即用的,因此您不必提供自定义 IEqualityComparer<TKey>
。
var pricePageDictionary = pricePageList
.ToDictionary(p => (p.VendorItemNo,p.SubSeasonStartDate,p.SubSeasonEndDate));
foreach (var item in availabilityItems)
{
var key = (item.Number,item.StartDate,item.EndDate);
if (pricePageDictionary.TryGetValue(key,out var page))
{
item.VendorItemNo = page.VendorItemNo;
item.PricePageNo = page.PricePageNo;
item.NaItemNo = page.ItemNo;
}
}
与嵌套循环方法相比,这应该非常快,因为在 Dictionary<TKey,TValue>
中搜索是一个 O(1) 操作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。