这是遍历字典的不正确方法吗?

时间:2019-03-29 05:10:57

标签: vb.net dictionary

以以下方式遍历字典是否存在任何问题?

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循环。这使我质疑我使用的方法。

更新:请注意,我并不是在问如何遍历字典,而是我过去成功使用的方法是否错误以及为什么?

2 个答案:

答案 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)

基于此,我们看到迭代键/值对实际上更快。

这种循环看起来像(其中KeyValuePairkvp):

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