excel 按关键字对字典进行排序

shstlldc  于 2023-11-20  发布在  其他
关注(0)|答案(6)|浏览(177)

我已经使用CreateObject("Scripting.Dictionary")创建了一个字典,它将源单词Map到目标单词,以便在某些文本中替换(这实际上是为了混淆)。
不幸的是,当我按照下面的代码进行实际替换时,它会按照源单词添加到字典中的顺序替换源单词。例如,如果我有“Blue”,然后是“Blue Berry”,则“Blue Berry”中的“Blue”部分会被第一个目标替换,而“Berry”保持不变。

'This is where I replace the values
For Each curKey In dctRepl.keys()
    largeTxt = Replace(largeTxt, curKey, dctRepl(curKey))
Next

字符串
我想我可以通过首先将字典的从最长长度到最短长度排序,然后如上所述进行替换来解决这个问题。问题是我不知道如何以这种方式对键进行排序。

c9x0cxw0

c9x0cxw01#

看起来好像是我自己弄明白的。我创建了下面的函数,它似乎正在完成这项工作:

Public Function funcSortKeysByLengthDesc(dctList As Object) As Object
    Dim arrTemp() As String
    Dim curKey As Variant
    Dim itX As Integer
    Dim itY As Integer

    'Only sort if more than one item in the dict
    If dctList.Count > 1 Then

        'Populate the array
        ReDim arrTemp(dctList.Count - 1)
        itX = 0
        For Each curKey In dctList
            arrTemp(itX) = curKey
            itX = itX + 1
        Next

        'Do the sort in the array
        For itX = 0 To (dctList.Count - 2)
            For itY = (itX + 1) To (dctList.Count - 1)
                If Len(arrTemp(itX)) < Len(arrTemp(itY)) Then
                    curKey = arrTemp(itY)
                    arrTemp(itY) = arrTemp(itX)
                    arrTemp(itX) = curKey
                End If
            Next
        Next

        'Create the new dictionary
        Set funcSortKeysByLengthDesc = CreateObject("Scripting.Dictionary")
        For itX = 0 To (dctList.Count - 1)
            funcSortKeysByLengthDesc.Add arrTemp(itX), dctList(arrTemp(itX))
        Next

    Else
        Set funcSortKeysByLengthDesc = dctList
    End If
End Function

字符串
有关静态数组的更多信息,请参见:https://excelmacromastery.com/excel-vba-array/#Declaring_an_Array

zzlelutf

zzlelutf2#

我正在寻找一个简单的函数来排序字典升序键值在Microsoft Excel中。
我对neelsg的代码做了一些小的修改以适应我的目的(请参阅下面的'//注解以了解修改的详细信息):

'/* Wrapper (accurate function name) */
Public Function funcSortDictByKeyAscending(dctList As Object) As Object
    Set funcSortDictByKeyAscending = funcSortKeysByLengthDesc(dctList)
End Function

'/* neelsg's code (modified) */
Public Function funcSortKeysByLengthDesc(dctList As Object) As Object
'//    Dim arrTemp() As String
    Dim arrTemp() As Variant
...
...
...
        'Do the sort in the array
        For itX = 0 To (dctList.Count - 2)
            For itY = (itX + 1) To (dctList.Count - 1)
'//                If Len(arrTemp(itX)) < Len(arrTemp(itY)) Then
                If arrTemp(itX) > arrTemp(itY) Then
...
...
...
        'Create the new dictionary
'//        Set funcSortKeysByLengthDesc = CreateObject("Scripting.Dictionary")
        Set d = CreateObject("Scripting.Dictionary")
        For itX = 0 To (dctList.Count - 1)
'//            funcSortKeysByLengthDesc.Add arrTemp(itX), dctList(arrTemp(itX))
            d(arrTemp(itX)) = dctList(arrTemp(itX))
        Next
'// Added:
        Set funcSortKeysByLengthDesc = d
    Else
        Set funcSortKeysByLengthDesc = dctList
    End If
End Function

字符串

jvlzgdj9

jvlzgdj93#

另一种可能性是使用ArrayList对Dictionary键进行排序,然后使用ArrayList值重新创建Dictionary。

Private Sub SortDictionary(oDictionary As Scripting.Dictionary)
  On Error Resume Next
  Dim oArrayList As Object
  Dim oNewDictionary As Scripting.Dictionary
  Dim vKeys As Variant, vKey As Variant
     Set oArrayList = CreateObject("System.Collections.ArrayList")

     ' Transpose Keys into ones based array.
     vKeys = oDictionary.Keys
     vKeys = Application.WorksheetFunction.Transpose(vKeys)
     For Each vKey In vKeys
         Call oArrayList.Add(vKey)
     Next
     oArrayList.Sort
     ''oArrayList.Reverse
   
     ' Create a new dictionary with the same characteristics as the old dictionary.
     Set oNewDictionary = New Scripting.Dictionary
     oNewDictionary.CompareMode = oDictionary.CompareMode

     ' Iterate over the array list and transfer values from old dictionary to new dictionary.
     For Each vKey In oArrayList
         sKey = CStr(vKey)
         If oDictionary.Exists(sKey) Then
             Call oNewDictionary.Add(sKey, oDictionary.Item(sKey))
         End If
     Next
 
     ' Replace the old dictionary with new sorted dictionary.
     Set oDictionary = oNewDictionary
     Set oNewDictionary = Nothing: Set oArrayList = Nothing
 On Error GoTo 0
 End Sub

字符串

vsdwdz23

vsdwdz234#

我知道这是一个旧的线程,但它是有帮助的,当我遇到类似的问题。我的解决方案是使用沙箱工作表,让Excel排序键,然后只是重建字典。通过使用沙箱工作表,你可以很容易地使用公式,否则困难的排序情况,而不必编写自己的泡沫排序的键。在原海报的情况下,按Len(Key)降序排序可以解决这个问题。
下面是我的代码:

Private Sub SortDictionary(oDictionary As Scripting.Dictionary, oSandboxSheet As Worksheet)
On Error Resume Next
Dim oSortRange As Range
Dim oNewDictionary As Scripting.Dictionary
Dim lBegRow As Long, lEndRow As Long, lBegCol As Long, lEndCol As Long
Dim lIndex As Long
Dim sKey As String
Dim vKeys As Variant

    ' Transpose Keys into ones based array.
    vKeys = oDictionary.Keys
    vKeys = Application.WorksheetFunction.Transpose(vKeys)

    ' Calculate sheet rows and columns based upon array dimensions.
    lBegRow = LBound(vKeys, 1): lEndRow = UBound(vKeys, 1)
    lBegCol = LBound(vKeys, 2): lEndCol = UBound(vKeys, 2)

    With oSandboxSheet
        .Activate
        .Cells.EntireColumn.Clear

        ' Copy the keys to Excel Range calculated from Keys array dimensions.
        .Range(.Cells(lBegRow, lBegCol), .Cells(lEndRow, lEndCol)).Value = vKeys
        .Cells.EntireColumn.AutoFit
    
        ' Sort the entire range.
        Set oSortRange = .Range(.Cells(lBegRow, lBegCol), .Cells(lEndRow, lEndCol))
        With .Sort
            With .SortFields
                .Clear
                Call .Add(Key:=oSortRange, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal)
            End With
        
            Call .SetRange(oSortRange)
            .Header = xlNo
            .MatchCase = False
            .Orientation = xlTopToBottom
            .SortMethod = xlPinYin
            .Apply
        End With
    
        ' Recreate the keys now sorted as desired.
        vKeys = .Range(.Cells(lBegRow, lBegCol), .Cells(lEndRow, lEndCol)).Value
    End With

    ' Create a new dictionary with the same characteristics as the old dictionary.
    Set oNewDictionary = New Scripting.Dictionary
    oNewDictionary.CompareMode = oDictionary.CompareMode

    ' Iterate over the new sorted keys and transfer values from old dictionary to new dictionary.
    For lIndex = LBound(vKeys, 1) To UBound(vKeys, 1)
        sKey = vKeys(lIndex, 1)
        If oDictionary.Exists(sKey) Then
            Call oNewDictionary.Add(sKey, oDictionary.Item(sKey))
        End If
    Next

    ' Replace the old dictionary with new sorted dictionary.    
    Set oDictionary = oNewDictionary
    Set oNewDictionary = Nothing: Set oSortRange = Nothing
On Error GoTo 0
End Sub

字符串

pjngdqdw

pjngdqdw5#

可以通过在过程中添加代码来对键进行排序,而无需创建函数。

Dim sdkey,tamp As Variant
With CreateObject("Scripting.Dictionary")
sdkey = .keys
For i = LBound(sdkey) + 1 To UBound(sdkey)    ' We've listed the unique values as alphabetically.
For j = LBound(sdkey) To UBound(sdkey) - 1
If sdkey(j) > sdkey(i) Then
tamp = sdkey(j)
sdkey(j) = sdkey(i)
sdkey(i) = tamp
End If
Next j
Next i

ReDim tamp(1 To UBound(sd_key) + 1, 1 To 2)
…

字符串


的数据
示例文件源:Get sum of distinct values in Excel

vcudknz3

vcudknz36#

或者现在你可以得到一个排序键的数组,并使用它来重新创建字典,或者不重新创建就按顺序遍历字典,方法是:
arrSortedKeys = Application.WorksheetFunction.Sort(Application.WorksheetFunction.Transpose(myDictionary.Keys))

相关问题