VBAのハッシュテーブル/連想配列


90

VBAでハッシュテーブルまたは連想配列を作成する方法を説明するドキュメントが見つからないようです。可能ですか?

記事にリンクしたり、コードを投稿したりできますか?



回答:


109

Microsoft Scripting RuntimeライブラリにあるDictionaryオブジェクトを探していると思います。(VBEの[ツール...参照]メニューからプロジェクトへの参照を追加します。)

バリアントに適合できる単純な値でほとんど機能します(キーを配列にすることはできません。オブジェクトにしようとしても意味がありません。以下の@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

ニーズが単純で文字列キーだけが必要な場合は、VBAコレクションオブジェクトを使用することもできます。

どちらかが実際にハッシュするかどうかはわかりません。ハッシュテーブルのようなパフォーマンスが必要な場合は、さらに掘り下げることをお勧めします。(編集:Scripting.Dictionaryは内部的にハッシュテーブルを使用します。)


はい-辞書が答えです。私もこのサイトで答えを見つけました。stackoverflow.com/questions/915317/...
user158017

2
これは非常に良い答えです。しかし、キーはオブジェクトではありません。実際に起こっていることは、オブジェクトのデフォルトプロパティが文字列としてキャストされ、キーとして使用されていることです。オブジェクトに既定のプロパティ(通常は 'name')が定義されていない場合、これは機能しません。
Nigel Heffernan 2014年

@ナイル、ありがとう。確かにあなたは正しいと思います。また、オブジェクトにデフォルトのプロパティがない場合、対応するディクショナリキーはになりEmptyます。私はそれに応じて回答を編集しました。
jtolle 2015

いくつかのデータ構造は、here-説明analystcave.com/... エクセルVBA-に.NEXTのハッシュテーブルを使用するには、どのようにこのポストを示しstackoverflow.com/questions/8677949/...
ジョニーなぜ

上記のリンクの誤植:.NEXTではなく.NET。
ジョニーなぜ



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

VB(A)アプリで使用するには:

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

18
コードを投稿する新しいユーザーに反対票を投じるつもりはありませんが、通常「ハッシュテーブル」と呼ばれるものは、基礎となる実装が実際にはハッシュテーブルであることを意味します。ここにあるのは、通常の配列と線形検索で実装された連想配列です。違いについては、こちらを参照してください:en.wikipedia.org/wiki/Hash_table
jtolle

7
確かに。ハッシュテーブルのポイントは、キーの「ハッシュ」が基になるストレージ内のその値の場所(または、重複するキーが許可されている場合は少なくとも十分近い)につながるため、コストがかかる可能性のある検索の必要性を排除します。
Cor_Blimey

3
ハッシュテーブルが大きい場合は速度が遅すぎます。17,000エントリの追加には15秒以上かかります。辞書を使えば6秒以内に50万件追加できます。mscorlibハッシュテーブルを使用して3秒未満で500,000。
Christopher Thomas Nicodemus
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.