我一直无法阐明 ILookup
< 之间的差异/a> 和 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
是单个组(即键控序列),类似于 KeyValuePair
,其中值实际上是元素序列 (而不是单个元素)
-
IEnumerable>
是这些序列的序列(类似于迭代 IDictionary
IDictionary 时得到的结果) code>
- ILookup 更像是
IDictionary
,其中值实际上是元素序列
I've been having trouble articulating the differences between ILookup<TKey, TVal>
and IGrouping<TKey, TVal>
, and am curious if I understand it correctly now. LINQ compounded the issue by producing sequences of IGrouping
items while also giving me a ToLookup
extension method. So it felt like they were the same until I looked more closely.
var q1 =
from n in N
group n by n.MyKey into g
select g;
// q1 is IEnumerable<IGrouping<TKey, TVal>>
Which is equivalent to:
var q2 = N.GroupBy(n => n.MyKey, n => n);
// q2 is IEnumerable<IGrouping<TKey, TVal>>
Which looks a lot like:
var q3 = N.ToLookup(n => n.MyKey, n => n);
// q3 is ILookup<TKey, TVal>
Am I correct in the following analogies?
- An
IGrouping<TKey, TVal>
is a single group (i.e. a keyed sequence), analogous to KeyValuePair<TKey, TVal>
where the value is actually a sequence of elements (rather than a single element)
- An
IEnumerable<IGrouping<TKey, TVal>>
is a sequence of those (similar to what you get when iterating over an IDictionary<TKey, TVal>
- An
ILookup<TKey, TVal>
is more like a IDictionary<TKey, TVal>
where the value is actually a sequence of elements
发布评论
评论(3)
是的,所有这些都是正确的。
并且
ILookup
还扩展了IEnumerable>
,因此您可以迭代所有键/集合对(或者改为of) 只是查找特定的键。我基本上认为
ILookup
就像IDictionary>
一样。请记住,
ToLookup
是“立即执行”操作(立即执行),而GroupBy
是延迟操作。碰巧的是,按照“pull LINQ”的工作方式,当您开始从GroupBy
的结果中提取IGrouping
时,它必须读取所有数据(因为你不能中途切换组),而在其他实现中它可能能够产生流结果。 (在 Push LINQ 中确实如此;我希望 LINQ to Events 也是如此。)Yes, all of those are correct.
And
ILookup<TKey, TValue>
also extendsIEnumerable<IGrouping<TKey, TValue>>
so you can iterate over all the key/collection pairs as well as (or instead of) just looking up particular keys.I basically think of
ILookup<TKey,TValue>
as being likeIDictionary<TKey, IEnumerable<TValue>>
.Bear in mind that
ToLookup
is a "do it now" operation (immediate execution) whereas aGroupBy
is deferred. As it happens, with the way that "pull LINQ" works, when you start pullingIGrouping
s from the result of aGroupBy
, it has to read all the data anyway (because you can't switch group midway through) whereas in other implementations it may be able to produce a streaming result. (It does in Push LINQ; I would expect LINQ to Events to be the same.)GroupBy
和ToLookUp
具有几乎相同的功能除了:参考让我们使用示例代码来消除差异。假设我们有一个代表
Person
模型的类:之后我们定义一个
personnel
列表,如下所示:现在我需要将
personnels
分组按他们的水平。我这里有两种方法。使用GroupBy
或ToLookUp
。如果我使用GroupBy
,如前所述,它将使用延迟执行,这意味着,当您迭代集合时,下一个项目可能会也可能不会被计算,直到它被调用为止。在上面的代码中,我首先对人员进行了分组,但在迭代之前,我删除了一些人员。由于
GroupBy
采用的是延迟执行,所以最终的结果不会包含被移除的项,因为分组会在此处的foreach
点进行计算。输出:
但是如果我将上面的代码重写如下:(注意,代码与之前的代码相同,除了
GroupBy
被ToLookUp
替换)As
ToLookUp 使用立即执行,这意味着当我调用
ToLookUp
方法时,会生成结果并应用组,因此如果我在迭代之前从personnels
中删除任何项目,不会影响最终结果。输出:
注意:
GroupBy
和ToLookUp
也返回不同的类型。您可以使用 ToDictionary 而不是 ToLookUp,但需要注意这一点:(参考)
GroupBy
andToLookUp
has almost same functionality EXCEPT this: ReferenceLets clear the difference using sample code. suppose that we have a class representing
Person
model:after that we define a list of
personnels
as below:Now I need to get the
personnels
grouped by their level. I have two approach here. usingGroupBy
orToLookUp
. If I useGroupBy
, as stated before, it will use deferred execution, this means, that when you iterate through the collection the next item may or may not be computed until it is called for.In the above code, I firstly grouped the
personnels
, but before iterating it, I removed somepersonnels
. AsGroupBy
uses deferred execution, so the final result will not include the removed items, because grouping will be computing in theforeach
point here.Output:
But if I rewrite the above code as below:(note that code is same as the previous code except
GroupBy
is replaced byToLookUp
)As
ToLookUp
uses immediate execution, it means that when I call theToLookUp
method, result is generated and group is applied, so if I remove any item frompersonnels
prior to iteration, that wont effect the final result.Output:
Note:
GroupBy
andToLookUp
both return different types too.You might use ToDictionary instead of ToLookUp, but you need to pay attention to this:(reference)
ILookup 和 IDictionary 之间还有另一个重要区别:前者强制执行不变性,因为没有方法可以更改数据(除非使用者执行显式强制转换)。相比之下,IDictionary 具有“Add”等允许更改数据的方法。因此,从函数式编程和/或并行编程的角度来看,ILookup 更好。
(顺便说一句,似乎值得指出的是,IEnumerable 和 IList 之间的关系有点类似于 ILookup 和 IDictionary 之间的关系 - 前者是不可变的,后者不是。)
There is another important difference between ILookup and IDictionary: the former enforces immutability in the sense that here are no methods for changing the data (except when the consumer performs an explicit cast). By contrast, IDictionary has methods like "Add" which allow changing the data. So, from the perspective of functional-programming and/or parallel programming, ILookup is nicer.
(Btw., it seems worth pointing out that the relationship between IEnumerable and IList is somewhat similar to the one between ILookup and IDictionary - the former is immutable, the latter is not.)