我有一个List
的Objects
(大约100k),必须迭代才能生成Dictionary
。
但是代码执行得非常慢,特别是在一行上
public class Item{
public int ID;
public int Secondary_ID;
public string Text;
public int Number;
}
数据看起来像(100k行)
ID | Secondary_ID | Text | Number
1 | 1 | "something" | 3
1 | 1 | "something else"| 7
1 | 1 | "something1" | 4
1 | 2 | "something2" | 344
2 | 3 | "something3" | 74
2 | 3 | "something4" | 1
我希望完成后看起来像这样。 (老实说,任何收藏都可以)
Dictionary<int, string>
Key | Value
(secondary_ID) | (Text : Number)
1 | "Something : 3, Something else : 7, Something1 : 4"
2 | "Something2 : 344"
3 | "Something3 : 74, Something4 : 1"
我的代码当前的工作方式如下:
ListAll
包含所有数据。var Final=new Dictionary<int, string>();
var id1s=ListAll.Select(x => x.ID).Distinct().ToList();
foreach(var id1 in id1s) {
var shortList=ListAll.Where(x => x.ID==id1).ToList(); //99% of time spent is here
var id2s=shortList.Select(x => x.Secondary_ID).Distinct().ToList();
foreach(var id2 in id2s) {
var s=new StringBuilder();
var items=shortList.Where(x => x.Secondary_ID==id2).ToList();
foreach(var i in items) {
s.Append(String.Format("{0} : {1}", i.Text, i.Number));
}
Final.Add(id2, s.ToString());
}
}
return Final;
现在输出是正确的,但是如上面的注释所述,这花费了非常长的时间(90秒-肯定比我满意的多),并且想知道是否有更快的方法来实现。
该代码仅会使用一次,因此实际上并不是正常用法,因此我通常会忽略该原因,但出于学习目的而感到疑惑。
最佳答案
按ID对项目进行分组的一种更有效(甚至更容易编写)的方法是使用GroupBy
。
var query = ListAll.GroupBy(x => x.Secondary_ID)
.ToDictionary(group => group.Key,
group => string.Join(", ",
group.Select(item => string.Format("{0} : {1}",item.Text , item.Number))),
//consider refactoring part of this line out to another method
});
由于您的代码如此之慢的原因,您正在整个列表中搜索每个不同的ID。那是一个O(n ^ 2)运算。
GroupBy
不这样做。它在内部根据您要分组的内容使用基于哈希的结构,因此它可以快速(在O(1)时间内)找到任何给定项目所属的存储桶,而不是在O(n)时间内用你的方法。