字典的通配符搜索

Wildcard search of dictionary

在搜索 google 和 SO 之后,我看到有一种方法可以让我在字典中搜索现有键:

dict.exists("search string")

我的问题是如何使用通配符搜索字典:

dict.exists("search*")

我想先在字典中搜索一个术语,因为我的宏有用户 select 一组文件(文件名作为字典键,完整路径作为值),我想确定如果在我迭代字典元素以应用文件处理之前,组中存在某种命名约定的文件。

如果找到某种命名约定,则对字典中的每个文件进行 X 处理而不是 Y 处理 运行。诀窍在于,如果ANY的元素遵循一定的命名约定,那么它们都需要进行相应的处理。也就是说,如果1-19元素不符合约定,但是有20个元素通过了,那么1-20元素都需要具体处理。这就是为什么我不能边走边检查每个名字并一次 select 只处理一个文件的原因。

我目前的解决方案是在搜索命名约定后迭代整个字典,然后在我知道使用哪种方法处理文件后重复字典。我循环遍历所有元素两次,但似乎效率不高...

各位有没有合理的通配符搜索字典键的方案?

此方法可以帮助您在字典中搜索通配符

Sub test()
Dim Dic As Object: Set Dic = CreateObject("Scripting.Dictionary")
Dim KeY, i&: i = 1
For Each oCell In Range("A1:A10")
    Dic.Add i, Cells(i, 1).Value: i = i + 1
Next
For Each KeY In Dic
    If LCase(Dic(KeY)) Like LCase("Search*") Then
        MsgBox "Wildcard exist!"
        Exit For
    End If
Next
End Sub

Dictionary Items 方法return是所有项目的数组。您可以将它们连接成一个大字符串,然后使用 Instr() 确定您的搜索字符串是否在大字符串中。

从你的例子来看,你的末尾有星号,所以我假设你关心的是一个项目是如何开始的,而不是子字符串存在于任何地方。所以我寻找 delimiter+substring 并将分隔符添加到 Join 的前面(为了第一项)。如果你有不同的要求,你就得调整,但原理是一样的。

我使用两个竖线作为分隔符,因为它不太可能出现在数据中并且 return 是误报。这可能不适合您的数据。

Public Function WildExists(ByRef dc As Scripting.Dictionary, ByVal sSearch As String) As Boolean        
    Const sDELIM As String = "||"        
    WildExists = InStr(1, sDELIM & Join(dc.Keys, sDELIM), sDELIM & sSearch) > 0        
End Function

测试码

Sub Test()

    Dim dc As Scripting.Dictionary            
    Set dc = New Scripting.Dictionary

    dc.Add "Apple", "Apple"
    dc.Add "Banana", "Banana"
    dc.Add "Pear", "Pear"

    Debug.Print WildExists(dc, "App") 'true
    Debug.Print WildExists(dc, "Ora") 'false

End Sub

您可以使用 Filter 结合字典键数组来return匹配键数组。

Function getMatchingKeys(DataDictionary As Dictionary, MatchString As String, Optional Include As Boolean = True, Optional Compare As VbCompareMethod = vbTextCompare) As String()

    getMatchingKeys = Filter(DataDictionary.Keys, MatchString, Include, Compare)

End Function

下面是一些示例,说明在对字典的键应用过滤器时可以执行的操作。

选项显式

Sub Examples()
    Dim dict As Dictionary
    Dim arrKeys() As String
    Dim key

    Set dict = New Dictionary

    dict.Add "Red Delicious apples", 10
    dict.Add "Golden Delicious Apples", 5
    dict.Add "Granny Smith apples", 66
    dict.Add "Gala Apples", 20
    dict.Add "McIntosh Apples", 30
    dict.Add "Apple Pie", 40
    dict.Add "Apple Sauce", 50

    dict.Add "Anjuo Pears", 60
    dict.Add "Asian Pears", 22
    dict.Add "Bartlett Pears", 33
    dict.Add "Bosc Pears", 44
    dict.Add "Comice Pears", 3

    arrKeys = getMatchingKeys(dict, "Apple")
    Debug.Print "Keys that contain Apple"
    Debug.Print Join(arrKeys, ",")
    Debug.Print

    arrKeys = getMatchingKeys(dict, "Apple", False)
    Debug.Print "Keys that do not contain Apple"
    Debug.Print Join(arrKeys, ",")
    Debug.Print

    arrKeys = getMatchingKeys(DataDictionary:=dict, MatchString:="Apple", Include:=True, Compare:=vbBinaryCompare)
    Debug.Print "Keys that contain matching case Apple"
    Debug.Print Join(arrKeys, ",")
    Debug.Print

    arrKeys = getMatchingKeys(DataDictionary:=dict, MatchString:="Pears", Include:=True, Compare:=vbTextCompare)
    Debug.Print "We can also use the array of keys to find the values in the dictionary"
    Debug.Print "We have " & (UBound(arrKeys) + 1) & " types of Pears"
    For Each key In arrKeys
        Debug.Print "There are " & dict(key) & " " & key
    Next

End Sub

输出:

如果您想使用通配符在字典键中搜索,您可以使用方法 [yourdictionary].Keys 和函数 Application.Match

例如: Dim position As Variant '它将 return 第一次出现的位置

position = Application.Match("*Gonzalez", phoneBook.Keys, 0)

如果电话簿有键:(JuanCarlos、LuisGonzalez、PedroGonzalez)

它将 return LuisGonzalez

的位置