我有一组以下格式的数据,虽然非常简化:
我正在尝试获得一个最终结果,它给出了AccountCode总结的数据,所以在上述数据的情况下如下:
我通过创建一系列名为OutputData
的不同帐户代码,然后浏览将帐户代码与SelectedDealerData
中的相同字段进行比较并将其添加到现有值的数据来完成此操作:< / p>
For i = 0 To UBound(SelectedDealerData)
For j = 0 To UBound(OutputData)
If SelectedDealerData(i).AccountNumber = OutputData(j).AccountNumber And SelectedDealerData(i).Year = OutputData(j).Year Then
OutputData(j).Units = OutputData(j).Units + SelectedDealerData(i).Units
Exit For
End If
Next j
Next i
每个都有大约10,00个经销商和600-1000个帐户代码,因此这意味着需要进行大量不必要的循环。
有人能指出我更有效的解决方案吗?我在想某种词典比较,但我不确定如何实现它。
答案 0 :(得分:1)
为词典添加对 Microsoft Scripting Runtime 的引用:
Dim aggregated As Dictionary
Set aggregated = New Dictionary
For i = 0 To UBound(SelectedDealerData)
With SelectedDealerData(i)
If aggregated.Exists(.AccountCode) Then
aggregated(.AccountCode) = aggregated(.AccountCode) + .Value
Else
aggregated(.AccountCode) = .Value
End If
End With
Next
For Each Key In aggregated.Keys
Debug.? Key, aggregated(Key)
Next
答案 1 :(得分:0)
代码很慢,因为这里有1000万次比较和分配操作(10,000 x 1000)。
此外,循环收集不是非常有效,但是没有任何事情可以做,因为设计已经设置并保持原样。
有两种方法可以提高效率(您可以立即计算代码并查看这些步骤后的节省百分比)。
And
正在进行两项条件检查。即使第一个是假的(没有短路),VBA也会评估两者。所以放置嵌套的if then
条件,这样如果第一个条件失败,你就不会继续检查第二个条件。此外,在外部if
语句中保持条件更可能失败(因此它会快速失败并移动到下一个元素)。充其量,你在这里得到一个小的减速带,最糟糕的是,你并没有变得更糟。
这里发生的比较太多了。改变这一点太晚了,但如果您可以对集合进行排序或构建维护其排序顺序的索引(如果您愿意,请将该索引数组保存在电子表格中),您可以根据以下伪代码浏览循环。排序应该基于名为Account_Number_Year的复合字段完成(只是将它们连接起来)
您可以在Alex K建议的字典结构中使用此连接字段。因此,您可以在第二个字典中查找此关节字段,然后根据需要执行操作。
尝试在VBA中完全实现它的代码:
'Assuming both arrays are sorted
For i = 0 to Ni
MatchingIndex = _
BinarySearchForAccNumberYear(SelectedUserData(i).AccountNumberYear)
Next i
您可以查找二进制搜索here。
这会将您的时间复杂度从O(n ^ 2)减少到O(n log n),并且您的代码运行速度会提高一个数量级。