VBA의 해시 테이블 / 연관 배열


답변:


111

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 2009-08-21

2
그것은 꽤 좋은 대답입니다. 그러나 키는 결코 객체가 아닙니다. 실제로 일어나는 것은 객체의 기본 속성이 문자열로 캐스팅되고 키로 사용된다는 것입니다. 객체에 기본 속성 (일반적으로 'name')이 정의되어 있지 않으면 작동하지 않습니다.
Nigel Heffernan

@Nile, 감사합니다. 나는 당신이 정말로 옳다는 것을 압니다. 또한 객체에 기본 속성이없는 경우 해당 사전 키는 Empty입니다. 그에 따라 답변을 편집했습니다.
jtolle

여기에 여러 데이터 구조가 설명되어 있습니다.- analyzercave.com/… 이 게시물은 Excel VBA에서 .NEXT 해시 테이블을 사용하는 방법을 보여줍니다 .- stackoverflow.com/questions/8677949/…
why

위 링크 오타 : .NEXT가 아닌 .NET.
johny 왜



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.
크리스토퍼 토마스 니고데모
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.