比较两个数据集 - 慢

时间:2014-07-09 12:07:41

标签: arrays vba dictionary collections

我有一组以下格式的数据,虽然非常简化:

  • DealerName,AccountCode,Value
  • 经销商1,A-1,5
  • 经销商2,A-1,10
  • 经销商1,A-2,20
  • 经销商2,A-2,15
  • 经销商3,A-3,5

我正在尝试获得一个最终结果,它给出了AccountCode总结的数据,所以在上述数据的情况下如下:

  • AccountCode,Value
  • A-1,15
  • A-2,35
  • A-3,5

我通过创建一系列名为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个帐户代码,因此这意味着需要进行大量不必要的循环。

有人能指出我更有效的解决方案吗?我在想某种词典比较,但我不确定如何实现它。

2 个答案:

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

此外,循环收集不是非常有效,但是没有任何事情可以做,因为设计已经设置并保持原样。

有两种方法可以提高效率(您可以立即计算代码并查看这些步骤后的节省百分比)。

  1. And正在进行两项条件检查。即使第一个是假的(没有短路),VBA也会评估两者。所以放置嵌套的if then条件,这样如果第一个条件失败,你就不会继续检查第二个条件。此外,在外部if语句中保持条件更可能失败(因此它会快速失败并移动到下一个元素)。充其量,你在这里得到一个小的减速带,最糟糕的是,你并没有变得更糟。

  2. 这里发生的比较太多了。改变这一点太晚了,但如果您可以对集合进行排序或构建维护其排序顺序的索引(如果您愿意,请将该索引数组保存在电子表格中),您可以根据以下伪代码浏览循环。排序应该基于名为Account_Number_Year的复合字段完成(只是将它们连接起来)

  3. 您可以在Alex K建议的字典结构中使用此连接字段。因此,您可以在第二个字典中查找此关节字段,然后根据需要执行操作。

  4. 尝试在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),并且您的代码运行速度会提高一个数量级。