以以下方式遍历字典是否存在任何问题?
Dim dict As New Dictionary(Of String, Integer) From {{"One", 1}, {"Two", 2}, {"Three", 3}}
For i = 0 To dict.Count - 1
Dim Key = dict.Keys(i)
Dim Value = dict.Item(Key)
'Do more work
dict.Item(Key) = NewValue
Next
我已经使用了很多,没有任何问题。但是我最近读到,迭代字典的最佳方法是使用ForEach
循环。这使我质疑我使用的方法。
更新:请注意,我并不是在问如何遍历字典,而是我过去成功使用的方法是否错误以及为什么?
答案 0 :(得分:4)
以以下方式遍历字典是否有问题?
是,不是。从技术上讲,您的操作方式并没有本质上的错误,因为它可以完成您需要执行的操作, 但 它需要不必要的计算,因此比简单地使用a慢For Each
循环并重复键/值对。
Keys
属性不是键的单独集合,而实际上只是字典本身的一个薄包装,它仅包含用于枚举键的枚举器。因此,它也没有索引器,可让您像现在一样在特定索引处访问密钥。
实际上发生的是VB.NET正在使用扩展方法ElementAtOrDefault()
,该方法通过逐步进行枚举直到达到所需的索引来起作用。这意味着对于主循环的每次迭代,ElementAtOrDefault()
也会执行类似的逐步迭代,直到到达您指定的索引为止。现在,您有两个循环,导致 O(N * N)= O(N 2 )操作。
此外,当您通过Item(Key)
访问值时,它必须计算键的哈希值并确定要获取的相应值。尽管此操作接近 O(1),但与下面要讲的相比,它仍然是不必要的附加操作。
字典已经有一个内部列表(数组),其中包含键及其各自的值,因此使用For Each
循环迭代字典时,它要做的就是获取每一对并将它们放入{{1} }。由于这一次它是直接通过索引(在特定的内存位置)获取的,因此您只有一个循环,因此获取操作为 O(1),从而使整个循环为 O(N * 1)= O(N)。
基于此,我们看到迭代键/值对实际上更快。
这种循环看起来像(其中KeyValuePair
是kvp
):
KeyValuePair(Of String, Integer)
答案 1 :(得分:1)
查看此处:
https://www.dotnetperls.com/dictionary-vbnet
键。您可以获取字典键列表。字典具有带有标识符键的get访问器属性。您可以将Keys传递给List构造函数以获得Key的List。
它引用了一个类似于您的示例:
Module Module1
Sub Main()
' Put four keys and values in the Dictionary.
Dim dictionary As New Dictionary(Of String, Integer)
dictionary.Add("please", 12)
dictionary.Add("help", 11)
dictionary.Add("poor", 10)
dictionary.Add("people", -11)
' Put keys into List Of String.
Dim list As New List(Of String)(dictionary.Keys)
' Loop over each string.
Dim str As String
For Each str In list
' Print string and also Item(string), which is the value.
Console.WriteLine("{0}, {1}", str, dictionary.Item(str))
Next
End Sub
End Module