【问题标题】:How to speed up the comparision of 2 collections in VBA?如何加快 VBA 中 2 个集合的比较速度?
【发布时间】:2015-10-06 18:23:07
【问题描述】:

我编写了一个宏,它获取集合的集合,然后获取两个集合并给我相似性。 现在,如果我用一个简单的 for 循环比较这两个集合,那么比较 pCol 中包含的所有 854 个集合需要几个小时。 这是我的代码:

    Function CompareCollections(ByVal pCol As Collection) As Collection
    Dim outer As Long
    Dim inner As Long
    'collections that will be compared to each other
    Dim inCol As Collection
    Dim outCol As Collection
    'collection used for return values
    Dim retCol As Collection
    'result of single comparison
    Dim res As CompResult
    'comparison variables
    Dim iIdx As Long
    Dim oIdx As Long
    Dim same As Long

    Set retCol = New Collection
    For outer = 1 To pCol.Count - 1
        Set outCol = pCol(outer)
        For inner = outer + 1 To pCol.Count
            Set inCol = pCol(inner)

            Set res = New CompResult
            res.LeftTable = outCol(1) 'index 1 contains a header
            res.RightTable = inCol(1)

            'compare the two collections <== PART I WANT TO SPEED UP
            same = 0
            For oIdx = 2 To outCol.Count 'starting with 2 to ignore the header
                For iIdx = 2 To inCol.Count
                    If inCol(iIdx) = outCol(oIdx) Then same = same + 1
                Next iIdx
                DoEvents
            Next oIdx
            res.Result1 = same / (outCol.Count - 1)
            res.Result2 = same / (inCol.Count - 1)
            retCol.Add res

            Set res = Nothing
            Set inCol = Nothing
            DoEvents
        Next inner
        Set outCol = Nothing
        DoEvents
    Next outer
    Set CompareCollections = retCol
End Function

我真的希望你们能帮助我。

编辑: CompResult 类是一个简单的结构,因为我无法将自定义类型添加到集合中:

Private mLeftTable As String
Private mRightTable As String
Private mResult1 As Double
Private mResult2 As Double

Public Property Get LeftTable() As String
    LeftTable = mLeftTable
End Property

Public Property Let LeftTable(value As String)
    mLeftTable = value
End Property

Public Property Get RightTable() As String
    RightTable = mRightTable
End Property

Public Property Let RightTable(value As String)
    mRightTable = value
End Property

Public Property Get Result1() As Double
    Result = mResult1
End Property

Public Property Let Result1(value As Double)
    mResult1 = value
End Property

Public Property Get Result2() As Double
    Result = mResult2
End Property

Public Property Let Result2(value As Double)
    mResult2 = value
End Property

【问题讨论】:

  • 拜托,你能发布 CompResult 类吗?
  • 使用 ArrayLlist 代替 - 然后您可以使用 .Contains() 方法。或者使用Dictionary 类并使用.Exists() 来查看是否有匹配项。请注意,Dictionary 必须包含唯一键,而 ArrayList 则不需要。
  • @MacroMan 感谢您的提示。它真的让它快了很多。现在我只需要找到一种快速的方法将我的庞大集合(>300k 元素)写入 Excel 表
  • @TimvdBerg 使用.ToArray() 方法,然后使用Range.Resize() 一口气写完。
  • @MacroMan 谢谢。 .ToArray() 就像一个魅力。唯一的问题是,单独调整大小并不能帮助我一口气写出来。这样做的原因是我有一个嵌套数组,其中包含一个二维数组。你知道一个技巧可以让我完成这项工作吗?

标签: excel vba


【解决方案1】:

第一个提示:尝试预先计算 outCol.Count、inCol.Count 和 pCol.Count 以避免不必要的计算。

第二个提示:如果在您的对象 CompResult 中 res.Result1 和 res.Result2 是整数,请使用“\”而不是“/”。

第三个提示:尽可能使用整数而不是长值。

第四个技巧:在为每一列循环时,尝试用“for each”循环替换 for 循环。好像快了一点。

最后一个技巧可能是转换数组中的集合(范围)并遍历它们,因为它似乎比遍历范围更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    相关资源
    最近更新 更多