我已经有麻烦阐明之间的差异 ILookup<TKey, TVal>IGrouping<TKey, TVal>, 我很好奇如果我的理解是正确的。皇宫加剧了这一问题通过生产序列 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>

我正在下面的比喻?

  1. 一个 IGrouping<TKey, TVal> 是一个单一的组(即键顺序),类似于 KeyValuePair<TKey, TVal> 其中值是实际上的序列元素(而不是单个元素)
  2. 一个 IEnumerable<IGrouping<TKey, TVal>> 是一个顺序(相似你会得到什么,当一个迭代 IDictionary<TKey, TVal>
  3. 一个 ILookup<TKey, TVal> 更像是 IDictionary<TKey, TVal> 其中值实际上是一种序列的元素
有帮助吗?

解决方案

是的,所有这些都是正确的。

ILookup<TKey, TValue> 还延伸 IEnumerable<IGrouping<TKey, TValue>> 所以你可以迭代过的所有关键/收集对以及(或不是)只是寻找特定的钥匙。

我基本上认为的 ILookup<TKey,TValue> 作为喜欢 IDictionary<TKey, IEnumerable<TValue>>.

铭记 ToLookup 是"现在就这样做"操作(即时执行),而一个 GroupBy 被推迟。如发生这种情况,与的方式,以"拉皇宫"运作,当你开始拉 IGroupings的结果 GroupBy, 它具有读所有数据(因为你不能开关组中通过)而在其他的实现方式也可能能够产生一流的结果。(它在推皇宫;我希望皇宫的事件是相同的。)

其他提示

还有另外一个重要的差异之间的ILookup和IDictionary:前者强制执行不可变性的意义上说,这是无法改变的数据(除非消费者执行一个明确的铸).相比之下,IDictionary有方法,如"增加",允许改变的数据。因此,从这个角度的功能编程和/或平行编程,ILookup是更好。(我只希望还有一个版本的ILookup分配的唯一价值的一个关键,而不是一个组。)

(顺便说一句., 它似乎值得指出的是,之间的关系类型和IList是有点类似于一个之间的ILookup和IDictionary-前是不可改变的,后者不是。)

GroupByToLookUp 有几乎相同的功能 除了 这样的: 参考

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 分组通过他们的水平。我有两个方法在这里。使用 GroupByToLookUp.如果我用 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

注: GroupByToLookUp 两者的回归不同的类型。

你可能会使用ToDictionary而不是ToLookUp,但是你需要注意这一点:(参考)

使用的ToLookup()非常相似的ToDictionary(), 两者都允许你到指定的关键选择、价值选择,以及 比较器.主要差别是,ToLookup()允许(和 预期)的重复键而ToDictionary()不

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top