快速查找阵列VBA中的特定Object.Name字符串的方法

时间:2015-11-19 10:44:00

标签: arrays vba

我有一个带对象的数组。这些对象有一个名为“Name”的属性。您当然可以通过Object.Name :)读出它。我现在正在寻找一种快速方法来查找具有指定名称的Object的索引。

我需要做大约30000次,所以它需要一个快速的方式。

2 个答案:

答案 0 :(得分:1)

执行此操作的最有效方法是创建Scripting.Dictionary类的其他模块级对象,该对象将用于映射项目名称及其索引。

乍一看,它似乎浪费时间和内存,因为需要额外的对象,并且需要使用数组中已存在的数据填充它。但是对于非常多的迭代次数(并且你说你需要做大约30000次),这个成本很快就会被我们使用字典所获得的收益所超越。

以下是展示这种态度的一个例子:

Option Explicit

'This must be module-level variable.
Dim indexMap As Object


Public Sub test()
    Const COUNTER As Long = 5000
    Const ITERATIONS As Long = 1000000
    '-------------------------------------------------------
    Dim items() As Object
    Dim startTime As Double
    Dim name As String
    Dim index As Long
    Dim i As Long
    '-------------------------------------------------------

    'Create an array of items for test.
    items = createArrayForTest(COUNTER)


    'Get the current timestamp to check how long it took.
    startTime = VBA.Timer

    'Create a dictionary that will be used as a map index-itemName.
    Set indexMap = createIndexMap(items)

    'Actual test
    For i = 1 To ITERATIONS

        'Create some random name for which the function will find its index.
        name = "item_" & VBA.Int(VBA.Rnd * 1000)
        index = findIndex(name)

    Next i


    Debug.Print COUNTER & " items | " & _
                ITERATIONS & " iterations | " & _
                "Time: " & Format(VBA.Timer - startTime, "#.##") & "s"


End Sub



Private Function createArrayForTest(COUNTER As Long) As Object()
    Dim arr() As Object
    Dim item As Obj
    Dim i As Long
    '-------------------------------------------------------

    ReDim arr(1 To COUNTER)

    For i = 1 To COUNTER
        Set item = New Obj
        item.name = "item_" & i
        Set arr(i) = item
    Next i

    createArrayForTest = arr

End Function


Private Function createIndexMap(items() As Object) As Object
    Dim i As Long
    '-------------------------------------------------------

    'Create dictionary and populate it with the items from the given array.
    'The name of each item is the key, and the index of this item is the value.
    Set createIndexMap = VBA.CreateObject("Scripting.Dictionary")
    With createIndexMap
        For i = LBound(items) To UBound(items)
            Call .Add(items(i).name, i)
        Next i
    End With

End Function


Public Function findIndex(name As String) As Long

    With indexMap
        If .exists(name) Then
            findIndex = .item(name)
        Else
            'If there is no item with such name, the function
            'returns -1.
            findIndex = -1
        End If
    End With

End Function

我对基本数组中的项目数和要查找的索引数的各种组合进行了一些测试。以下是结果:

5000 items | 1000000 iterations | Time: 4,59s
10000 items | 100000 iterations | Time: 0,52s
30000 items | 100000 iterations | Time: 0,85s
30000 items | 1000000 iterations | Time: 7,41s

答案 1 :(得分:1)

这样的事可以帮到你:

Function Get_Index_From_Name(anArray As Variant, ObjectName As String)
Dim i As Long

For i = LBound(anArray) To UBound(anArray)
    If anArray(i).Name <> ObjectName Then
    Else
        Get_Index_From_Name = i
        Exit Function
    End If
Next i

End Function