2

辞書の特定のキーとアイテムのペアの後にアイテムを追加する必要があります。add メンバーがコレクションで許可するのと本質的に同じ動作: (Collection.Add (item [,key] [,before] [,after])

4

3 に答える 3

5

これを可能にするDictionaryオブジェクトの組み込みメソッドはありません。これがあなた自身を転がす簡単な方法です。これはあなたが求めていることを具体的に達成しますが、変更するのは簡単です:

Function DictAdd(StartingDict As Dictionary, Key, Item, AfterKey) As Dictionary
Dim DictKey As Variant

    Set DictAdd = New Dictionary
    For Each DictKey In StartingDict
        DictAdd.Add DictKey, StartingDict(DictKey)
        If DictKey = AfterKey Then DictAdd.Add Key, Item
    Next DictKey
End Function

そしてそれをテストするには、次の手順を実行します。

Sub TestDictAdd()
Dim MyDict As New Dictionary, DictKey As Variant

    MyDict.Add "A", "Alpha"
    MyDict.Add "C", "Charlie"

    Set MyDict = DictAdd(MyDict, "B", "Bravo", "A")
    For Each DictKey In MyDict
        Debug.Print DictKey, MyDict(DictKey)
    Next DictKey
End Sub

これはあなたが始めるためだけのものです。これを自分で行う場合は、関数を使用する代わりに、使用する独自のカスタムクラスを作成し、カスタムAddメソッドを作成する可能性があります。また、次の改善を行います。

  • エラー処理を追加
  • AfterKeyをオプションのパラメータにする
  • オプションのパラメータとしてBeforeKeyを追加します
于 2012-05-28T19:55:53.097 に答える
1

このような?

Option Explicit

Sub Sample()
    Dim Dict As Dictionary
    Dim itm As Variant

    Set Dict = New Dictionary

    Dict.Add "MyKey1", "Hello"
    Dict.Add "MyKey2", "This"
    Dict.Add "MyKey3", "is"
    Dict.Add "MyKey4", "Example"

    '~~> USAGE: Dictionaty Object, Key, Text, Position        
    Additem Dict, "MyKey5", "An", 3

    For Each itm In Dict
        Debug.Print itm & " - " & Dict(itm)
    Next
End Sub

Function Additem(ByRef D As Dictionary, ky As Variant, itm As Variant, pos As Long)
    Dim kyAr() As Variant, itmAr() As Variant
    Dim temp1() As Variant, temp2() As Variant
    Dim i As Long

    kyAr = D.Keys: itmAr = D.Items

    ReDim temp1(UBound(kyAr) + 1)
    ReDim temp2(UBound(itmAr) + 1)

    For i = 0 To pos - 1
        temp1(i) = kyAr(i): temp2(i) = itmAr(i)
    Next

    temp1(pos) = ky: temp2(pos) = itm

    For i = pos + 1 To UBound(temp1)
        temp1(i) = kyAr(i - 1): temp2(i) = itmAr(i - 1)
    Next

    ReDim kyAr(0): ReDim itmAr(0)

    kyAr() = temp1(): itmAr() = temp2()

    D.RemoveAll

    For i = LBound(kyAr) To UBound(kyAr)
        D.Add kyAr(i), itmAr(i)
    Next i
End Function

出力

MyKey1 - Hello
MyKey2 - This
MyKey3 - is
MyKey4 - Example

MyKey1 - Hello
MyKey2 - This
MyKey3 - is
MyKey5 - An
MyKey4 - Example
于 2012-05-28T19:57:20.943 に答える
1

ディクショナリにすべての項目が含まれている場合にディクショナリをソートする代わりに、DctAdd という小さなプロシージャを実装しました。これは、項目を追加するときにキーをすぐにソートしたままにします。キーが vAdd であると仮定すると、アイテムは vItem であり、バリアント型と並べ替えられるディクショナリの両方が dct です。代わりに:

dct.Add vAdd, vItem

私が使う:

DctAdd dct, vItem, vAdd, dam_sortasc 

パフォーマンスについては、プロジェクトで使用するときに十分であることがわかったので、いくつかの基本的なテストのみを含めました。

DctAdd を使用するには、関連するモジュールの宣言セクションに以下をコピーする必要があります。

' Just for the performance time measurement -----------------------------
Private Declare Function GetTime Lib "winmm.dll" Alias "timeGetTime" () As Long
' For the execution mode of DctAdd --------------------------------------
' (may be extended to also cover insert before and after)
Public Enum enAddInsertMode
    dam_sortasc = 1
    dam_sortdesc = 2
End Enum

次のコードは、任意の標準モジュールまたはクラス モジュールにコピーできます。insert before/after はまだ実装されていませんが、追加にそれほど時間はかからないことに注意してください。

Public Sub DctAdd(ByRef dct As Scripting.Dictionary, _
                  ByVal vItem As Variant, _
                  ByVal vAdd As Variant, _
                  ByVal lMode As enAddInsertMode)
' ----------------------------------------------------------------------
' Add to the Dictionary dct the item vItem with vAdd as the key,
' sorted in ascending or descending order.
'
' If the vAdd key already exists, adding it will be skipped without
' an error. A not existing dictionary is established with the first add
'
' W. Rauschenberger, warbe@cogip.de, Berlin, Feb 2015
' ----------------------------------------------------------------------
Dim i           As Long
Dim dctTemp     As Scripting.Dictionary
Dim vTempKey    As Variant
Dim bAdd        As Boolean

    If dct Is Nothing Then Set dct = New Dictionary

    With dct
        If .count = 0 Then
            .Add vAdd, vItem
            Exit Sub
        Else
            ' -----------------------------------------------------------
            ' The can maybee added directly after the last key
            ' -----------------------------------------------------------
            vTempKey = .Keys()(.count - 1)      ' Get the very last key
            Select Case lMode
                Case dam_sortasc
                    If vAdd > vTempKey Then
                        .Add vAdd, vItem
                        Exit Sub                ' Done!
                    End If
                Case dam_sortdesc
                    If vAdd < vTempKey Then
                        .Add vAdd, vItem
                        Exit Sub                ' Done!
                    End If
            End Select
        End If
    End With

    ' -----------------------------------------------------------------
    ' Since the new key could not simply be added to the dct it must be
    ' added/inserted somewhere in between or before the very first key
    ' ------------------------------------------------------------------
    Set dctTemp = New Dictionary
    bAdd = True
    For Each vTempKey In dct
        With dctTemp
            If bAdd Then ' When the new item has yet not been added
                Select Case lMode
                    Case dam_sortasc
                        If vTempKey > vAdd Then
                            If Not dct.Exists(vAdd) Then
                               .Add vAdd, vItem
                            End If
                            bAdd = False ' Add done
                        End If
                    Case dam_sortdesc
                        If vTempKey < vAdd Then
                            If Not dct.Exists(vAdd) Then
                                .Add vAdd, vItem
                            End If
                            bAdd = False ' Add done
                        End If
                End Select
            End If
            .Add vTempKey, dct.Item(vTempKey)
        End With
    Next vTempKey
                               ' ------------------------------------
    Set dct = dctTemp          ' Return the temporary dictionary with
    Set dctTemp = Nothing      ' the added new item
    Exit Sub                   ' ------------------------------------

on_error:
   Debug.Print "Error in 'DctAdd'!"
End Sub

そして、これをテストに使用しました:

Public Sub Testdct1Add()
Dim dct1    As Scripting.Dictionary
Dim dct2    As Scripting.Dictionary
Dim i       As Long
Dim lStart  As Long
Dim lAdd    As Long
Dim vKey    As Variant


    ' -----------------------------------------------------------------------
    Debug.Print vbLf & "DctAdd: Test ascending order"
    ' Add sorted ascending with the key provided in the reverse order
    Set dct1 = Nothing
    For i = 10 To 1 Step -1
        DctAdd dct1, i, i, dam_sortasc
    Next i
    ' Show the result and wait ----------------
    For Each vKey In dct1
        Debug.Print vKey & " " & dct1.Item(vKey)
    Next vKey
    Stop

    ' ------------------------------------------------------------------
    Debug.Print vbLf & "DctAdd: Test descending order"
    ' Add sorted ascending with the key provided in the reverse order
    Set dct1 = Nothing
    For i = 1 To 10
        DctAdd dct1, i, i, dam_sortdesc
    Next i
    ' Show the result and wait ----------------
    For Each vKey In dct1
        Debug.Print vKey & " " & dct1.Item(vKey)
    Next vKey
    Stop

    ' ------------------------------------------------------------------
    lAdd = 500
    Debug.Print vbLf & "DctAdd: Test a best case scenario by adding " & _
                vbLf & lAdd & " items in the desired sort order"
    Set dct1 = Nothing
    lStart = GetTime
    For i = 1 To lAdd
        DctAdd dct1, i, i, dam_sortasc
    Next i
    Debug.Print "Adding " & dct1.count & " items in the target " & _
         vbLf & "sort order = " & GetTime - lStart & " ms"
    Stop

    ' ------------------------------------------------------------------
    lAdd = 500
    Debug.Print vbLf & "DctAdd: Worst case scenarion test by adding " & _
                vbLf & lAdd & " items in the reverse sort order"
    Set dct1 = Nothing
    lStart = GetTime
    For i = lAdd To 1 Step -1
        DctAdd dct1, i, i, dam_sortasc
    Next i
    Debug.Print "Adding " & dct1.count & " items, 4 out of " & vbLf & _ 
                "order = " & GetTime - lStart & " ms"
    Stop

    ' -----------------------------------------------------------------
    lAdd = 1000
    Debug.Print vbLf & "DctAdd: Worst case scenarion test by adding " & _
                vbLf & lAdd & " items in the reverse sort order"
    Set dct1 = Nothing
    lStart = GetTime
    For i = lAdd To 1 Step -1
        DctAdd dct1, i, i, dam_sortasc
    Next i
    Debug.Print "Adding " & dct1.count & " items:" & vbLf & _
                GetTime - lStart & " ms"

    Stop

    ' -----------------------------------------------------------------
    ' Example for using dctAdd to sort any dictionary. The item if dct2 
    ' are temporarily added sorted ascending to the dct1 and finally set 
    ' to dct2
    ' ------------------------------------------------------------------
    Debug.Print vbLf & "DctAdd: Used to sort another Dictionary (dct2)"
    Set dct2 = New Dictionary
    dct2.Add "F", 1
    dct2.Add "A", 2
    dct2.Add "C", 3
    dct2.Add "H", 4
    dct2.Add "D", 5
    dct2.Add "E", 6
    dct2.Add "G", 7
    dct2.Add "B", 8

    Set dct1 = Nothing
    For Each vKey In dct2
        DctAdd dct1, dct2(vKey), vKey, dam_sortasc
    Next vKey
    Set dct2 = dct1
    ' Show the result and wait ----------------
    For Each vKey In dct2
        Debug.Print "Key=" & vKey & ", Item=" & dct2.Item(vKey)
    Next vKey

End Sub
于 2015-02-26T16:16:10.930 に答える