Reputation: 1950
So, I'm completely inexperienced with VBA (Visual Basic For Applications).
Basically, I have code that runs through dictionaries and removes certain elements from them. Here's a quick examples (that is NOT in the production code):
Dim testDict As New Scripting.Dictionary
testDict.Add 1, 5
testDict.Add 2, 10
testDict.Add 3, 15
testDict.Add 4, 20
testDict.Add 5, 25
testDict.Add 6, 30
Dim Key As Variant
For Each Key In testDict.Keys()
If testDict.Item(Key) = 5 Then
testDict.Remove (Key)
End If
If testDict.Item(Key) = 20 Then
testDict.Remove (Key)
End If
Next Key
I know that in some languages, this will throw off the underlying iterator. However I have no experience in Visual Basic, so I don't know how it works.
The reason I'm asking is that the above code works perfectly fine, and the algorithm which uses this approach works just fine too. I just need to have verified that this is a safe practice in VBA, and if not, how are cases like these usually dealt with in VBA?
Upvotes: 1
Views: 2133
Reputation: 1
In the first IF check of key value, he doesn't need to check if it exists because the key variable is being filled in through the loop. It has no other choice but to exist. However in the second IF check, he would need to check if exists because the key could have been removed from the dictionary in the first IF check. Besides this, as far as I can tell the code works fine.
Upvotes: 0
Reputation: 166351
The last line illustrates the problem with this approach.
Just referring to testDict.Item(Key)
will create a key if it doesn't exist, so you should always use testDict.Exists(Key)
before trying to check the value of a key which may not be present.
As for making deletions while looping over the keys, if you want to be sure then start by grabbing a copy of the keys and loop over that...
Added: if you add an item inside the loop it will not show up as a value of Key
variable.
Sub TT()
Dim testDict As New Scripting.Dictionary
testDict.Add 1, 5
testDict.Add 2, 10
testDict.Add 3, 15
testDict.Add 4, 20
testDict.Add 5, 25
testDict.Add 6, 30
Dim Key As Variant
For Each Key In testDict.Keys()
If testDict.Item(Key) = 5 Then
testDict.Remove (Key)
Debug.Print "Removed ", Key
End If
If testDict.Item(Key) = 20 Then
testDict.Remove (Key)
Debug.Print "Removed ", Key
End If
Next Key
'>>> Removed 1
'>>> Removed 4
Debug.Print Join(testDict.Keys, ",")
'>>> 2,3,5,6,1
End Sub
Upvotes: 2