VBA中的哈希表/关联数组

Tyl*_*ler 87 hash vba associative-array hashtable

我似乎无法找到解释如何在VBA中创建哈希表或关联数组的文档.它甚至可能吗?

你可以链接到一篇文章或更好地发布代码吗?

jto*_*lle 108

我想你正在寻找在Microsoft Scripting Runtime库中找到的Dictionary对象.(从VBE的Tools ... References菜单中添加对项目的引用.)

它几乎适用于任何适合变体的简单值(键不能是数组,并且尝试使它们成为对象没有多大意义.请参阅下面的@Nile中的注释.):

Dim d As dictionary
Set d = New dictionary

d("x") = 42
d(42) = "forty-two"
d(CVErr(xlErrValue)) = "Excel #VALUE!"
Set d(101) = New Collection
Run Code Online (Sandbox Code Playgroud)

如果您的需求更简单并且您只需要字符串键,也可以使用VBA Collection对象.

我不知道是否实际上有任何哈希值,所以如果你需要类似哈希表的性能,你可能想要进一步挖掘.(编辑:Scripting.Dictionary在内部使用哈希表.)

  • 这是一个很好的答案:但键从来都不是对象 - 实际发生的是对象的默认属性被转换为字符串并用作键。如果对象没有定义默认属性(通常是“名称”),这将不起作用。 (2认同)
  • 回复:“键永远不是对象” - 事实并非如此:您绝对可以添加一个对象(或至少是对该对象的引用)作为 Scripting.Dictionary 中的键,例如 `dict.Add Range("a1 "), "test" : arr = dict.keys: Debug.Print TypeName(arr(0))` 输出 "Range" (2认同)
  • ...从范围加载字典时,这可能会让您陷入困境,因为在设置键时不添加显式的“.Value”可能会导致各种奇怪的结果。 (2认同)

Mar*_*old 8

我曾经多次使用过Francesco Balena的HashTable类,当时Collection或Dictionary不是完美的,我只需要一个HashTable.


Dis*_*sco 7

尝试使用Dictionary对象或Collection对象.

http://visualbasic.ittoolbox.com/documents/dictionary-object-vs-collection-object-12196

  • 给定的链接不再起作用。原始发布时的内容可以在这里查看:https://web.archive.org/web/20090729034340/http://visualbasic.ittoolbox.com/documents/dictionary-object-vs-collection- object-12196 (2认同)

小智 6

在这里,我们去...只需将代码复制到模块,它就可以使用了

Private Type hashtable
    key As Variant
    value As Variant
End Type

Private GetErrMsg As String

Private Function CreateHashTable(htable() As hashtable) As Boolean
    GetErrMsg = ""
    On Error GoTo CreateErr
        ReDim htable(0)
        CreateHashTable = True
    Exit Function

CreateErr:
    CreateHashTable = False
    GetErrMsg = Err.Description
End Function

Private Function AddValue(htable() As hashtable, key As Variant, value As Variant) As Long
    GetErrMsg = ""
    On Error GoTo AddErr
        Dim idx As Long
        idx = UBound(htable) + 1

        Dim htVal As hashtable
        htVal.key = key
        htVal.value = value

        Dim i As Long
        For i = 1 To UBound(htable)
            If htable(i).key = key Then Err.Raise 9999, , "Key [" & CStr(key) & "] is not unique"
        Next i

        ReDim Preserve htable(idx)

        htable(idx) = htVal
        AddValue = idx
    Exit Function

AddErr:
    AddValue = 0
    GetErrMsg = Err.Description
End Function

Private Function RemoveValue(htable() As hashtable, key As Variant) As Boolean
    GetErrMsg = ""
    On Error GoTo RemoveErr

        Dim i As Long, idx As Long
        Dim htTemp() As hashtable
        idx = 0

        For i = 1 To UBound(htable)
            If htable(i).key <> key And IsEmpty(htable(i).key) = False Then
                ReDim Preserve htTemp(idx)
                AddValue htTemp, htable(i).key, htable(i).value
                idx = idx + 1
            End If
        Next i

        If UBound(htable) = UBound(htTemp) Then Err.Raise 9998, , "Key [" & CStr(key) & "] not found"

        htable = htTemp
        RemoveValue = True
    Exit Function

RemoveErr:
    RemoveValue = False
    GetErrMsg = Err.Description
End Function

Private Function GetValue(htable() As hashtable, key As Variant) As Variant
    GetErrMsg = ""
    On Error GoTo GetValueErr
        Dim found As Boolean
        found = False

        For i = 1 To UBound(htable)
            If htable(i).key = key And IsEmpty(htable(i).key) = False Then
                GetValue = htable(i).value
                Exit Function
            End If
        Next i
        Err.Raise 9997, , "Key [" & CStr(key) & "] not found"

    Exit Function

GetValueErr:
    GetValue = ""
    GetErrMsg = Err.Description
End Function

Private Function GetValueCount(htable() As hashtable) As Long
    GetErrMsg = ""
    On Error GoTo GetValueCountErr
        GetValueCount = UBound(htable)
    Exit Function

GetValueCountErr:
    GetValueCount = 0
    GetErrMsg = Err.Description
End Function
Run Code Online (Sandbox Code Playgroud)

要在VB(A)App中使用:

Public Sub Test()
    Dim hashtbl() As hashtable
    Debug.Print "Create Hashtable: " & CreateHashTable(hashtbl)
    Debug.Print ""
    Debug.Print "ID Test   Add V1: " & AddValue(hashtbl, "Hallo_0", "Testwert 0")
    Debug.Print "ID Test   Add V2: " & AddValue(hashtbl, "Hallo_0", "Testwert 0")
    Debug.Print "ID Test 1 Add V1: " & AddValue(hashtbl, "Hallo.1", "Testwert 1")
    Debug.Print "ID Test 2 Add V1: " & AddValue(hashtbl, "Hallo-2", "Testwert 2")
    Debug.Print "ID Test 3 Add V1: " & AddValue(hashtbl, "Hallo 3", "Testwert 3")
    Debug.Print ""
    Debug.Print "Test 1 Removed V1: " & RemoveValue(hashtbl, "Hallo_1")
    Debug.Print "Test 1 Removed V2: " & RemoveValue(hashtbl, "Hallo_1")
    Debug.Print "Test 2 Removed V1: " & RemoveValue(hashtbl, "Hallo-2")
    Debug.Print ""
    Debug.Print "Value Test 3: " & CStr(GetValue(hashtbl, "Hallo 3"))
    Debug.Print "Value Test 1: " & CStr(GetValue(hashtbl, "Hallo_1"))
    Debug.Print ""
    Debug.Print "Hashtable Content:"

    For i = 1 To UBound(hashtbl)
        Debug.Print CStr(i) & ": " & CStr(hashtbl(i).key) & " - " & CStr(hashtbl(i).value)
    Next i

    Debug.Print ""
    Debug.Print "Count: " & CStr(GetValueCount(hashtbl))
End Sub
Run Code Online (Sandbox Code Playgroud)

  • 我不打算推​​销一个发布代码的全新用户,但通常称之为"哈希表"意味着底层实现实际上是一个哈希表!你在这里有一个关联数组,使用常规数组和线性搜索实现.请参阅此处了解差异:http://en.wikipedia.org/wiki/Hash_table (18认同)
  • 确实.哈希表的重点是密钥的"哈希"导致其值在底层存储中的位置(或者至少在允许重复密钥的情况下足够近),因此消除了对潜在代价高昂的搜索的需要. (7认同)
  • 对于较大的哈希表来说太慢了.添加17,000个条目需要15秒.我可以使用字典在6秒内添加500,000.使用mscorlib哈希表在不到3秒的时间内完成500,000次. (3认同)