201

我试图围绕哪些数据结构最有效以及何时/何地使用哪些数据结构。

现在,可能是我只是对结构不够了解,但是ILookup(of key, ...)a 与 a 有什么不同Dictionary(of key, list(of ...))

另外,我想在ILookup哪里使用以及在程序速度/内存/数据访问等方面会更有效?

4

6 回答 6

307

两个显着差异:

  • Lookup是不可变的。耶 :) (至少,我相信具体Lookup类是不可变的,并且ILookup接口不提供任何可变成员。当然,可能还有其他可变实现。)
  • 当您查找一个不存在于查找中的键时,您会得到一个空序列而不是KeyNotFoundException. (因此没有TryGetValue,AFAICR。)

它们在效率上可能相当——例如,查找很可能Dictionary<TKey, GroupingImplementation<TValue>>在幕后使用 a 。根据您的要求在它们之间进行选择。就我个人而言,我发现查找通常比 a 更合适Dictionary<TKey, List<TValue>>,主要是由于上面的前两点。

请注意,作为实现细节,其具体实现IGrouping<,>用于值 implements IList<TValue>,这意味着使用 with 等是有效Count()ElementAt()

于 2012-11-13T14:33:15.503 回答
75

有趣的是,没有人说出实际最大的区别(直接取自MSDN):

查找类似于字典。不同之处在于 Dictionary 将键映射到单个值,而 Lookup 将键映射到值的集合。

于 2014-06-06T06:10:09.527 回答
36

aDictionary<Key, List<Value>>Lookup<Key, Value>逻辑上都可以保存以类似方式组织的数据,并且两者的效率顺序相同。主要区别是 aLookup是不可变的:它没有Add()方法,也没有公共构造函数(正如 Jon 提到的,您可以毫无例外地查询不存在的键,并将键作为分组的一部分)。

至于你使用哪个,这真的取决于你想如何使用它们。如果您正在维护一个不断修改的多个值的键映射,那么 aDictionary<Key, List<Value>>可能会更好,因为它是可变的。

但是,如果您有一个数据序列,并且只想要按键组织的数据的只读视图,那么查找非常容易构建,并且将为您提供只读快照。

于 2012-11-13T14:32:14.617 回答
13

另一个尚未提及的区别是 Lookup()支持空键

Lookup 类实现了 ILookup 接口。查找与字典非常相似,只是允许多个值映射到同一个键,并且支持空键。

于 2016-05-20T09:38:41.080 回答
12

ILookup<K,V>an和 a的主要区别在于Dictionary<K, List<V>>字典是可变的。您可以添加或删除键,还可以从查找的列表中添加或删除项目。AnILookup不可变的,一旦创建就不能修改。

两种机制的底层实现将相同或相似,因此它们的搜索速度和内存占用将大致相同。

于 2012-11-13T14:32:30.403 回答
6

当异常不是一个选项时,去查找

Dictionary如果您试图获得一个Lookup

正如另一个答案中提到的,它还支持空键,并且在使用任意数据查询时始终返回有效结果,因此它看起来对未知输入更具弹性(比 Dictionary 更不容易引发异常)。

如果将其与System.Linq.Enumerable.ToDictionary函数进行比较,则尤其如此:

// won't throw
new[] { 1, 1 }.ToLookup(x => x); 

// System.ArgumentException: An item with the same key has already been added.
new[] { 1, 1 }.ToDictionary(x => x);

foreach另一种方法是在循环内编写您自己的重复密钥管理代码。

性能考虑,字典:明显的赢家

如果您不需要列表并且要管理大量项目Dictionary(甚至您自己定制的结构)会更有效:

        Stopwatch stopwatch = new Stopwatch();
        var list = new List<string>();
        for (int i = 0; i < 5000000; ++i)
        {
            list.Add(i.ToString());
        }
        stopwatch.Start();
        var lookup = list.ToLookup(x => x);
        stopwatch.Stop();
        Console.WriteLine("Creation: " + stopwatch.Elapsed);

        // ... Same but for ToDictionary
        var lookup = list.ToDictionary(x => x);
        // ...

由于Lookup必须为每个键维护一个项目列表,它比 Dictionary 慢(对于大量项目,速度大约慢 3 倍)

查找速度:创建:00:00:01.5760444

字典速度:创建:00:00:00.4418833

于 2018-05-03T12:28:16.207 回答