GroupBy
并ToLookUp
具有几乎相同的功能(除此以外):参考
GroupBy:GroupBy运算符根据某个键值返回元素组。每个组由IGrouping对象表示。
ToLookup:ToLookup与GroupBy相同;唯一的区别是,GroupBy的执行被推迟,而ToLookup的执行是立即执行。
让我们使用示例代码清除差异。假设我们有一个表示Person
模型的类:
class Personnel
{
public int Id { get; set; }
public string FullName { get; set; }
public int Level { get; set; }
}
之后,我们定义personnels
如下列表:
var personnels = new List<Personnel>
{
new Personnel { Id = 1, FullName = "P1", Level = 1 },
new Personnel { Id = 2, FullName = "P2", Level = 2 },
new Personnel { Id = 3, FullName = "P3", Level = 1 },
new Personnel { Id = 4, FullName = "P4", Level = 1 },
new Personnel { Id = 5, FullName = "P5", Level =2 },
new Personnel { Id = 6, FullName = "P6", Level = 2 },
new Personnel { Id = 7, FullName = "P7", Level = 2 }
};
现在,我需要personnels
按级别进行分组。我这里有两种方法。使用GroupBy
或ToLookUp
。如果我使用GroupBy
,如前所述,它将使用延迟执行,这意味着,当您遍历集合时,下一个项目可能会或可能不会被计算,直到需要它为止。
var groups = personnels.GroupBy(p => p.Level);
personnels.RemoveAll(p => p.Level == 1);
foreach (var product in groups)
{
Console.WriteLine(product.Key);
foreach (var item in product)
Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level);
}
在上面的代码中,我首先对进行了分组personnels
,但是在对其进行迭代之前,我删除了一些personnels
。由于GroupBy
使用了延迟执行,因此最终结果将不包括删除的项目,因为分组将在foreach
此处进行计算。
输出:
2
2 >>> P2 >>> 2
5 >>> P5 >>> 2
6 >>> P6 >>> 2
7 >>> P7 >>> 2
但是,如果我将下面的代码重写如下:(请注意,该代码与之前的代码相同,只不过GroupBy
被替换了ToLookUp
)
var groups = personnels.ToLookup(p => p.Level);
personnels.RemoveAll(p => p.Level == 1);
foreach (var product in groups)
{
Console.WriteLine(product.Key);
foreach (var item in product)
Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level);
}
作为ToLookUp
用途立即执行,这意味着,当我调用ToLookUp
方法中,产生的结果和组被施加,因此如果删除从任何项目personnels
之前迭代中,这不会影响最后的结果。
输出:
1
1 >>> P1 >>> 1
3 >>> P3 >>> 1
4 >>> P4 >>> 1
2
2 >>> P2 >>> 2
5 >>> P5 >>> 2
6 >>> P6 >>> 2
7 >>> P7 >>> 2
注:GroupBy
和ToLookUp
都返回不同类型的了。
您可能使用ToDictionary而不是ToLookUp,但是您需要注意以下几点:(参考资料)
ToLookup()的用法与ToDictionary()的用法非常相似,都允许您指定键选择器,值选择器和比较器。主要区别在于ToLookup()允许(并期望)重复的键,而ToDictionary()不允许