我有一个带对象的数组。这些对象有一个名为“Name”的属性。您当然可以通过Object.Name :)读出它。我现在正在寻找一种快速方法来查找具有指定名称的Object的索引。
我需要做大约30000次,所以它需要一个快速的方式。
答案 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