title: Iterating through a Scripting.Dictionary/Collection object
body: <p>I have a project that's been changed and modified in bits and pieces over the past few years, and much from one code module to the next is non-standardized. In some cases, I have a <code>Scripting.Dictionary</code> object used and in others, I have a <code>Collection</code> object. For each of these, there are sometimes iterations by count (i.e. <code>For i = 1 to Obj.Count</code>) and sometimes by <code>For...Each</code>.</p>
  
  <p>I would like to apply the same logic for as many of these cases as possible to make future changes hopefully more seamless, but I'm not sure which methodology is best. (I believe some specific cases made be made for one or another method, but I'm also pretty sure some of the code could use any of the methods available.)</p>
  
  <p>I tried creating a testing sub to help me determine which of these methods works best, but the results were somewhat inconsistent. Overall, it appears that looping through each <code>Item</code> in a <code>Dictionary</code> is faster, but in some cases my tests came out showing a loop through each <code>Item</code> in a <code>Collection</code> is faster. The variance probably depends on everything else that's going on in the system at any given time. </p>
  
  <p>I was wondering if anyone had a definitive answer as to which method is consistently the fastest, assuming all else within the loop is the same. Or, is there some way to improve my testing sub to be more consistent when returning results so that I can answer this question myself?</p>
  
  
  
  <p>The testing code I've come up with:</p>
  
  <pre class="lang-vb prettyprint-override"><code>Option Explicit
  
  Sub Test_Dictionary_Iteration_Speed()
  
  Dim Coll1 As New Collection, Coll2 As New Collection
  Dim Dict1 As New Scripting.Dictionary, Dict2 As New Scripting.Dictionary, Dict3 As New Scripting.Dictionary
  Dim i As Integer, j As Integer, l As Integer
  Dim StartTime As Single, StopTime As Single
  Dim v As Variant
  Dim Obj As TestObject 'A custom Class that has only one member variable, MainVal, and no functions/subs
  
      For i = 0 To 32766
          Set Obj = New TestObject
          Obj.MainVal = i
          Dict1.Add CStr(i), Obj
          Dict2.Add CStr(i), Obj
          Dict3.Add CStr(i), Obj
          Coll1.Add Obj, CStr(i)
          Coll2.Add Obj, CStr(i)
      Next i
  
      StartTime = Timer()
  
      For j = 0 To Dict1.Count - 1
          l = CInt(Dict1(CStr(j)).MainVal)
          Set Obj = Dict1(CStr(l)) 'Do something useful within the loop
          Set Obj = Nothing
          Dict1.Remove CStr(l)
      Next j
  
      StopTime = Timer()
  
      Debug.Print "Dict1 for x to y: " &amp; StopTime - StartTime
  
      StartTime = Timer()
  
      For Each v In Dict2.Items
          l = CInt(v.MainVal)
          Set Obj = Dict2(CStr(l))
          Set Obj = Nothing
          Dict2.Remove CStr(l)
      Next v
  
      StopTime = Timer()
  
      Debug.Print "Dict2 for each item: " &amp; StopTime - StartTime
  
      StartTime = Timer()
  
      For Each v In Dict3.Keys
          l = CInt(Dict3(v).MainVal)
          Set Obj = Dict3(CStr(l))
          Set Obj = Nothing
          Dict3.Remove CStr(l)
      Next v
  
      StopTime = Timer()
  
      Debug.Print "Dict3 for each key: " &amp; StopTime - StartTime
  
      '---------- Division between Dictionary and Collection
  
      StartTime = Timer()
  
      For j = 0 To Coll1.Count - 1
          l = CInt(Coll1(CStr(j)).MainVal)
          Set Obj = Coll1(CStr(l))
          Set Obj = Nothing
          Coll1.Remove CStr(l)
      Next j
  
      StopTime = Timer()
  
      Debug.Print "Coll1 for x to y: " &amp; StopTime - StartTime
  
      StartTime = Timer()
  
      For Each v In Coll2
          l = CInt(v.MainVal)
          Set Obj = Coll2(CStr(l))
          Set Obj = Nothing
          Coll2.Remove CStr(l)
      Next v
  
      StopTime = Timer()
  
      Debug.Print "Coll2 for each item: " &amp; StopTime - StartTime
  
      Debug.Print vbNewLine &amp; "-----" &amp; vbNewLine   
  
  
  End Sub
  </code></pre>
  
  <p>Real examples of output, showing that the 'best' option is not always the same:</p>
  
  <blockquote>
    <p>Dict1 for x to y: 0.2011719<br>
    Dict2 for each item: 0.1738281<br>
    Dict3 for each key: 0.2167969<br>
    Coll1 for x to y: 0.2050781<br>
    Coll2 for each item: <strong>0.1386719</strong> </p>
    
    <hr>
    
    <p>Dict1 for x to y: 0.1875<br>
    Dict2 for each item: 0.171875<br>
    Dict3 for each key: 0.234375<br>
    Coll1 for x to y: 0.2050781<br>
    Coll2 for each item: <strong>0.1542969</strong>  </p>
    
    <hr>
    
    <p>Dict1 for x to y: 0.25<br>
    Dict2 for each item: 0.21875<br>
    Dict3 for each key: 0.265625<br>
    Coll1 for x to y: 0.234375<br>
    Coll2 for each item: <strong>0.171875</strong>  </p>
    
    <hr>
    
    <p>Dict1 for x to y: 0.265625<br>
    Dict2 for each item: <strong>0.203125</strong><br>
    Dict3 for each key: 0.296875<br>
    Coll1 for x to y: 0.234375<br>
    Coll2 for each item: 0.21875  </p>
    
    <hr>
    
    <p>Dict1 for x to y: 0.265625<br>
    Dict2 for each item: 0.1875<br>
    Dict3 for each key: 0.234375<br>
    Coll1 for x to y: 0.203125<br>
    Coll2 for each item: <strong>0.15625</strong>  </p>
    
    <hr>
    
    <p>Dict1 for x to y: 0.28125<br>
    Dict2 for each item: <strong>0.1875</strong><br>
    Dict3 for each key: 0.25<br>
    Coll1 for x to y: 0.234375<br>
    Coll2 for each item: <strong>0.1875</strong>  </p>
    
    <hr>
    
    <p>Dict1 for x to y: 0.28125<br>
    Dict2 for each item: <strong>0.21875</strong><br>
    Dict3 for each key: 0.328125<br>
    Coll1 for x to y: 0.234375<br>
    Coll2 for each item: 0.234375</p>
  </blockquote>