我一直难以阐明ILookup和IGrouping之间的区别,我很好奇我现在是否正确地理解了它。LINQ通过生成IGrouping项的序列,同时给出了ToLookup扩展方法,从而使问题更加复杂。所以在我仔细观察之前他们感觉是一样的。
var q1 =
from n in N
group n by n.MyKey into g
select g;
// q1 is IEnumerable<IGrouping<TKey, TVal>>相当于:
var q2 = N.GroupBy(n => n.MyKey, n => n);
// q2 is IEnumerable<IGrouping<TKey, TVal>>看起来很像:
var q3 = N.ToLookup(n => n.MyKey, n => n);
// q3 is ILookup<TKey, TVal>下面的类比我是正确的吗?
IGrouping<TKey, TVal>是单个组(即键控序列),类似于KeyValuePair<TKey, TVal>,其中值实际上是元素序列(而不是单个元素)。IEnumerable<IGrouping<TKey, TVal>>是这些序列的一个序列(类似于在IDictionary<TKey, TVal>上迭代时得到的结果)。ILookup<TKey, TVal>更像是一个IDictionary<TKey, TVal>,其中的值实际上是一个元素序列。发布于 2009-08-26 21:21:55
是的,所有这些都是正确的。
ILookup<TKey, TValue>还扩展了IEnumerable<IGrouping<TKey, TValue>>,这样您就可以遍历所有的键/集合对,以及(或代替)查找特定的键。
我基本上认为ILookup<TKey,TValue>就像IDictionary<TKey, IEnumerable<TValue>>一样。
请记住,ToLookup是“立即执行”操作(立即执行),而GroupBy是延迟执行的。碰巧的是,按照“拉LINQ”的工作方式,当您开始从一个IGrouping的结果中提取GroupBy时,它无论如何都必须读取所有的数据(因为您不能在中间切换组),而在其他实现中,它可能能够产生一个流结果。(在Push LINQ中是这样的;我希望LINQ对事件的影响是相同的。)
发布于 2018-08-08 09:15:12
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()不允许重复键
发布于 2013-06-05 16:00:57
ILookup和IDictionary还有另一个重要的区别:前者强制不可变,因为这里没有更改数据的方法(除非使用者执行显式强制转换)。相反,IDictionary有类似于"Add“的方法,这些方法允许更改数据。因此,从函数编程和/或并行编程的角度来看,ILookup更好。
(顺便说一句,似乎值得指出的是,IEnumerable和IList之间的关系有点类似于ILookup和IDictionary之间的关系--前者是不变的,后者则不是。)
https://stackoverflow.com/questions/1337539
复制相似问题