GroupBy 和 ToLookUp 具有几乎相同的功能除了:Reference
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,但您需要注意这一点:(reference)
ToLookup() 的用法与 ToDictionary() 非常相似,
两者都允许您指定键选择器、值选择器和
比较器。主要区别在于 ToLookup() 允许(和
期望)重复键,而 ToDictionary() 没有