Excel 在VBA中使用Select Case对两对字符串进行二进制比较

Excel 在VBA中使用Select Case对两对字符串进行二进制比较,excel,vba,Excel,Vba,我有20组两对字符串,每个字符串可以是1到5个字符。大多数情况下,它们实际上是介于1和52之间的整数,或者有时一个小数点位于1和53之间的浮点数(例如52.3)将是最大值。有时,使用大于或小于符号,并将最大字符数增加到5个,例如>26.2 这20组数据集将进行大量的比较,大约25k次,这意味着像下面这样的单个比较约500K次。我猜最好的存储选项是字符串,而不是每次都测试它,看它是字符串、整数还是浮点。但是如果我错了,请纠正我。字符串可以以任何方式配对,例如允许成对重复 我将以一组20个为例: 1

我有20组两对字符串,每个字符串可以是1到5个字符。大多数情况下,它们实际上是介于1和52之间的整数,或者有时一个小数点位于1和53之间的浮点数(例如52.3)将是最大值。有时,使用大于或小于符号,并将最大字符数增加到5个,例如>26.2

这20组数据集将进行大量的比较,大约25k次,这意味着像下面这样的单个比较约500K次。我猜最好的存储选项是字符串,而不是每次都测试它,看它是字符串、整数还是浮点。但是如果我错了,请纠正我。字符串可以以任何方式配对,例如允许成对重复

我将以一组20个为例:

12 13 13 14 让我们用字母来表示它们A、B、C和D,这样我们就不会忽略它们是字符串的事实,并看看它们是如何比较的。A=12、B=13和C=14……在这个例子中没有D,但在其他例子中可能有

AB 卑诗省 现在我们看到了这一点,我们可以推断出10种可能的匹配方式和3种可能的不匹配方式…根据它们的共享方式,7个值中的一个是从字典、集合或索引、数组或其他类似的方式返回的

AA股和AA股均双倍获得指数值1 AA AB股票第一次双倍获得指数值2 AA BA股票第一次双倍获得指数值2 AB AA股票第一双倍获得指数值2 AB BB股票第二双得指数值3 AB共享2获取索引值4 AB AC股票第一次一次获得指数值5 AB CA共享第一次获得指数值5 九,。AB BC共享第二次一次获取索引值6

AB CB股票第二次一次获得指数值6 AA BC share none获得索引值7 AB CD共享无获取索引值7 AB CC share none获取索引值7 在上面的12,13和13,14示例中,列表中的数字9是比较结果,我需要得到索引值6

抛开我如何得到索引值,或者这些集合是如何产生的,我想把重点放在决定返回哪个索引值的逻辑上。我尝试了一个大型嵌套的If-Ifelse,它的速度非常慢,大约为7小时,用于500k的比较。我想下一步是做一个嵌套的select案例,我将在这里展示:

For i = 0 To 20    
Select Case A
    Case B
        Select Case A
            Case C
                Select Case A
                    Case D                                                     
                        'code to get AAAA index value 1
                    Case Else                                                                   
                        'code to get AAAB index value 2
                End Select
            Case Else
                Select Case A
                    Case D                                                        
                        'code to get AABA index value 2
            Case Else
            'code to get AABC index value 7
                End Select
        End Select
    Case Else
        Select Case A
            Case C
                Select Case A
                    Case D                                                     
                        'code to get ABAA index value 2
                    Case Else 
                        Select Case B
                            Case D                                             
                                'code to get ABAB index value 4
                            Case Else                                                           
                                'code to get ABAC index value 5
                        End Select
                End Select
            Case Else
                Select Case B
                    Case C
                        Select Case B
                            Case D                                             
                                'code to get ABBB index value 3
                            Case Else                                                           
                                'code to get ABBC index value 6
                        End Select
                    Case Else
                        Select Case A
                            Case D                                             
                                'code to get ABCA index value 5
                            Case Else
                                Select Case B
                                    Case D                                     
                                       'code to get ABCB index value 6
                                    Case Else   
                                        'all thats left code to get ABCD and ABCC index value 7 
                                End Select
                        End Select
                End Select
        End Select
End Select
Next i
再一次…非常缓慢。我已经尝试过将字符串单独存储在数组、字典、类对象中,并对它们进行迭代,试图优化比较,但没有效果。我想我已经确定了这个比较是导致问题的原因。别误会我。对于一套20,闪电很快,但当我需要做50000次时,需要7个小时


我还没有尝试过,但我对外部VBScript或C++多线程代码比较感兴趣,我对VBSCPT C++或多线程一无所知,所以目前这是不可能的。那怎么样?有没有关于如何加快比较速度的建议?

我已经修改了一个示例代码。它基本上从4个输入参数创建一个4位代码字符串,然后在静态字典中查找分配给代码的值。虽然没有测试过所有的变化

在测试中,500.000次迭代在不到2秒内运行。这将根据您读取所有字符串的方式而增加,但比较本身不是问题所在

您将需要对脚本库的引用

Option Explicit
Dim codeTab As Dictionary

Sub test()
    Debug.Print getCode("12", "13", "13", "14")
End Sub

Sub initTab()
    Set codeTab = New Dictionary
    codeTab.Add "AAAA", 1
    codeTab.Add "AAAB", 2
    codeTab.Add "AABA", 2
    codeTab.Add "ABAA", 2
    codeTab.Add "ABBB", 3
    codeTab.Add "ABAB", 4
    codeTab.Add "ABAC", 5
    codeTab.Add "ABCA", 5
    codeTab.Add "ABBC", 6
    codeTab.Add "ABCB", 6
    codeTab.Add "AABC", 7
    codeTab.Add "ABCD", 7
    codeTab.Add "ABCC", 7
End Sub

Function getCode(p1 As String, p2 As String, p3 As String, p4 As String) As Integer

    Dim p(), code As String, nextFree As String
    ' Create an array out of the parameters to enable looping.
    p = Array(p1, p2, p3, p4)
    code = ""
    nextFree = "A"
    Dim i As Integer, j As Integer
    For i = 0 To 3   ' loop over all 4 values
        Dim found As Boolean: found = False
        For j = 0 To i - 1    ' compare the value with previous values
            If p(i) = p(j) Then     ' value already there, add matching letter
                found = True
                code = code & Mid(code, j + 1, 1)
                Exit For
            End If
        Next j
        If Not found Then    ' new value, use next free letter
            code = code & nextFree
            nextFree = Chr(Asc(nextFree) + 1)
        End If
    Next i

    ' Debug.Print code
    getCode = codeTab(code)
End Function

我发布这篇文章只是因为我之前说过我会的。我向数据库管理员论坛提出了我的问题,在一些建议最终回答了我自己的问题之后。我很乐意留下@FunThomas的答案,因为他至少回答了我当时想要的答案,希望这能帮助其他人。不过,我已经解决了使用三个表、一组派生表和一组联接进行二进制比较的问题。在5秒内进行67000次比较。我相信我可以通过更多的索引和优化sql以及任何前端代码来加速这个过程。谢谢你的帮助


我会把它移回去编辑这篇文章。我只是想让下面的人注意一下,以防他们想看一看。

对不起,我完全不明白你的问题-我想当你提到小数点和大于/小于号时,我已经听不懂了。每一个都是一个大集合中的数据点。每个点可以是整数值1、2、3或浮点数1.1、1.2…52.2,有时也可以是数据点26.2的一部分。因此,我选择使用一个数据类型字符串……并且我想比较两对字符串。如果您包含整个代码,而不仅仅是循环体,而不仅仅是占位符,那么这可能更适合
我考虑一下,谢谢!这是一段优美的代码。它比我写的要快一点,而且要熟练得多。如果你不介意的话,我将使用它并开始在我的代码中加入类似的东西。我将我的程序进一步细分,发现您和@MathieuGuinedon是正确的。这不是我的问题。最大的时间消耗来自ADO连接和recset检索,每个新的20个集合使用一个SQL存储过程。如果您感兴趣,我将在DBA中重新发布相关代码和存储的查询……我将在下一篇评论中链接它。实际上,我不需要DBA论坛。这是我的桌子结构。这20套中的每一套我都有20张桌子。我把它们放在一张桌子上,从7小时缩短到10分钟。我仍然喜欢你的答案@FunThomas,并已将其纳入其中。