Prove that Excel VBA Scripting.Dictionary does not preserve order of item insertion

前端 未结 1 1751
清酒与你
清酒与你 2021-01-19 05:18

I\'m trying to decide whether to use Excel VBA Collection or Dictionary for my project. For several reasons, I lean toward dictionary, but I keep reading that when using a <

相关标签:
1条回答
  • 2021-01-19 05:58

    No one can provide an example of a Scripting.Dictionary object returning keys/items in a different order than they were added because a Scripting.Dictionary does not do that. Never. If you add the following key/item pairs in a progressive order then that is the ways they are returned.

    key  item
     1    A
     2    B
     3    C
     4    D
    
    'enumerate by key
    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")
    
    dict.Add Key:=1, Item:="A"
    dict.Add Key:=2, Item:="B"
    dict.Add Key:=3, Item:="C"
    dict.Add Key:=4, Item:="D"
    
    Dim k As Variant
    For Each k In dict.Keys
        Debug.Print k & " - " & dict.Item(k)
    Next k
    

    You might be referring to the shorthand 'overwrite' method of adding keys without checking to see it they exist. If you try to .Add a key that exists error 457 is thrown. However, if you simply write Keys and Items into the dictionary a new key and item will be created if the key does not exist but if the key exists the key remains the same and the item is overwritten.

    key  item
     1    A
     2    B
     3    C
     4    D
     2    E
    
    'enumerate by key
    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")
    
    dict.Item(1) = "A"
    dict.Item(2) = "B"
    dict.Item(3) = "C"
    dict.Item(4) = "D"
    dict.Item(2) = "E"     'the second entry's item is overwritten
    
    Dim k As Variant
    For Each k In dict.Keys
        Debug.Print k & " - " & dict.Item(k)
    Next k
    

    The overwrite method is a little faster than checking if a key .Exists but the behavior should be understood. I've used the overwrite to intentionally retrieve the last item for any key in a list with duplicate keys but that was a special case. Note that the 2 .Key is not out of original order; it has merely had its .Item replaced with the later one.

    If you have added the Microsoft Scripting Runtime reference library you can use Early Binding in your variable declaration. This has the benefit of creating a slightly faster dictionary object and exposing other methods of indexed enumeration.

    Dim dict As New Scripting.Dictionary
    
    'enumerate by index position (zero-based index)
    Dim i As Long
    For i = 0 To dict.Count - 1
        Debug.Print dict.Keys(i) & " - " & dict.Items(i)
    Next i
    
    'enumerate as elements of an array
    Dim a As Long
    For a = LBound(dict.Keys) To UBound(dict.Keys)
        Debug.Print dict.Keys(a) & " - " & dict.Items(a)
    Next a
    

    fwiw, I've found this indexed enumeration unreliable when the dictionary's .Count exceeds a signed integer (32,767).

    Finally, key/item pairs can be removed one at a time or all at once.

    dict.Remove 2                              'remove by key
    
    dict.Remove dict.Keys(0)                   'remove first key/item by index position
    dict.Remove dict.Keys(UBound(dict.Keys))   'remove last key/item by index position
    
    dict.RemoveAll                             'remove all
    
    0 讨论(0)
提交回复
热议问题