foreach循环中对象的Filling List属性
本文关键字:Filling List 属性 对象 循环 foreach | 更新日期: 2023-09-27 18:27:38
我想知道在对象中填充对象列表是否可以比运行时更快。我填写CABCodes-&CABDetails使用带有.ToList()的Dapper通过简单查询列出;
因此,这两个列表都在内存中,但foreach操作大约需要20秒。
CAB代码:约10000个对象
CAB详细信息:约60000个对象
List<CABCode> CABCodes = new List<CABCode>();
List<CABDetail> CABDetails = new List<CABDetail>();
public class CABCode {
public int Sequence { get; set; }
public string Code { get; set; }
public int Group { get; set; }
public List<CABDetail> Details { get; set; }
}
public class CABDetail {
public int CABSequence { get; set; }
public int Proptype { get; set; }
public string Propvalue { get; set; }
}
foreach (var c in this.CABCodes) {
c.Details = this.CABDetails.Where(x => x.CABSequence == c.Sequence).ToList();
}
有没有更有效的方法来实现这一点?
您有O(M*N)算法时间。以下代码使其为O(M+N),这是快速的:
var cabDetailsBySequence = CABDetails.ToLookup(d=>d.CABSequence);
foreach (var c in this.CABCodes) {
c.Details = cabDetailsBySequence[c.Sequence].ToList();
}
更新:我检查过它能在110毫秒下工作,有100个不同的序列码。
以下是测试设置:
CABCodes = Enumerable.Range(0, 10000).Select(i=>new CABCode{Sequence = i%100}).ToList();
CABDetails = Enumerable.Range(0, 60000).Select(i=>new CABDetail{CABSequence = i%100}).ToList();
更新2:如果你不介意在不同的CABCode实例中引用相同的列表,你可以让它更快(大约20倍),如果你并行进行,速度会更快。这样,它在我的8核系统上运行不到一毫秒:
var cabDetailListsBySequence = cabDetailsBySequence.ToDictionary(i=>i.Key, i=>i.ToList());
// foreach (var c in this.CABCodes) {
// c.Details = cabDetailListsBySequence[c.Sequence];
// }
this.CABCodes.AsParallel().ForAll(c=>c.Details = cabDetailListsBySequence[c.Sequence]);
Linq并不总是像用if/else语句编写自己的循环那样快。第二件事是,ToList()创建一个List的新实例,这也会降低性能。
这个代码的性能如何:
foreach (var c in this.CABCodes)
{
var detailList = new List<CABDetail>();
foreach(var d in CAPDetails)
{
if (d.CABSquence == c.Sequence)
{
detailList.Add(d);
}
}
c.Details = detailList;
}
也许我在代码中犯了一些错误,因为我写得很快。