问答中心分类: VB.NETLookup() 和 Dictionary(Of list()) 的区别
0
匿名用户 提问 18分钟 前

我试图围绕哪些数据结构最有效以及何时/何地使用哪些数据结构。
现在,可能是我只是对结构不够了解,但是如何ILookup(of key, ...)不同于一个Dictionary(of key, list(of ...))?
我还想在哪里使用ILookup以及在程序速度/内存/数据访问等方面效率更高?

nawfal 回复 18分钟 前

可能还想看看什么是查找点关键元素

5 Answers
0
Mladen Mihajlovic 回答 18分钟 前

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

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

Martao 回复 18分钟 前

检查问题:这是关于查找之间的区别和字典>,所以这种差异已经很明显了。

jakubiszon 回复 18分钟 前

@Martao 有些人在谷歌搜索以了解查找和字典之间的区别时发现了这个问题。这个答案真的很有用。

OfirD 回复 18分钟 前

@Mladen Mihajlovic,我不明白 MSDN 的解释。 Dictionary 还可以将键映射到值的集合,例如通过传递一个列表:grouping.ToDictionary(g => g.Key, g => g.ToList()).

Mladen Mihajlovic 回复 18分钟 前

@OfirD 是的,从这个意义上说,它们是相同的。但正如其他答案所述,还有其他差异。

0
James Michael Hare 回答 18分钟 前

两者都是Dictionary<Key, List<Value>>和一个Lookup<Key, Value>逻辑上可以保存以类似方式组织的数据,并且两者具有相同的效率顺序。主要区别是一个Lookup是不可变的:它没有Add()方法并且没有公共构造函数(正如乔恩所提到的,您可以毫无例外地查询一个不存在的键,并将该键作为分组的一部分)。
至于你使用哪个,这真的取决于你想如何使用它们。如果您正在维护一个不断修改的多个值的键映射,那么Dictionary<Key, List<Value>>可能更好,因为它是可变的。
但是,如果您有一个数据序列,并且只想要按键组织的数据的只读视图,那么查找非常容易构建,并且将为您提供只读快照。

0
Noble_Bright_Life 回答 18分钟 前

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

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

0
Servy 回答 18分钟 前

之间的主要区别ILookup<K,V>和一个Dictionary<K, List<V>>是字典是可变的吗?您可以添加或删除键,还可以从查找的列表中添加或删除项目。一个ILookup不可变并且一旦创建就不能修改。
两种机制的底层实现将相同或相似,因此它们的搜索速度和内存占用将大致相同。

Servy 回复 18分钟 前

@JohnBus​​tos 在性能方面,没有。这纯粹是合乎逻辑的。您可以传递对结构的引用,而不必担心其他人会从您下面修改它。你可以假设它是不可变的,如果它是可变的,你就不能。

John Bustos 回复 18分钟 前

谢谢,Servy,当你经常传递这么多变量 ByRef 时,这是一个非常好的观点——至少这个你确定不能被修改。谢谢!

Servy 回复 18分钟 前

@JohnBus​​tos 请记住,传递方法参数的默认方法是按值传递,您需要显式添加 byref,这是很少应该做的事情。这些数据结构是类,这使得它们成为引用类型,因此传递值就是引用的值,这就是为什么将其传递给另一个方法会导致调用者可见的变化。

John Bustos 回复 18分钟 前

谢谢,Servy,就我一直在做的事情而言,这为我打开了一个全新的蠕虫罐头:),但我明白你在说什么。谢谢!!

paparazzo 回复 18分钟 前

在幕后,您是否知道 Lookup 是否使用 hashbuckets 作为密钥?

Servy 回复 18分钟 前

@Blam我有理由确定它确实如此,但可能不是确切地相同,只是一个类似的通用算法。

Dave Black 回复 18分钟 前

对@Servy 评论“传递参数的默认方法是按值”的一个澄清……所有变量在 C# 中默认按值传递。对于值类型,您正在制作副本。在引用类型的情况下,您正在传递参考价值(不复制)。当然,除非您添加ref关键字传递对 ValueType 的引用或对 ReferenceType 的引用的引用。

0
Fab 回答 18分钟 前

当异常不是一个选项时,去查找
如果你想获得一个像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

PM Extra 回复 18分钟 前

我认为这种性能比较是不公平的。对于相同的结果,list.ToLookup(x => x)等于list.GroupBy(x => x).ToDictionary(group => group.Key).因为 Lookup 可以枚举出你一开始说的重复元素。

GreatBittern 回复 18分钟 前

为了提高性能,从 ILookup 或 Dictionary 中查看检索更有趣。典型的用途是只创建一次,并进行频繁的查找。因此,我不会太在意构建它的性能。

Mr.Z 回复 18分钟 前

谢谢你写这篇文章。我想指出,“性能注意事项”部分可能需要更加清晰,因为它令人不安地暗示Lookup在做不是为它设计的事情时表现更差,即将 1 个键映射到 1 个值。