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

时间:2019-02-12 15:41:53

标签: excel vba

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

将对这组20组进行大量比较(大约25k左右,这意味着一次比较的〜500K,如下图所示)。我的猜测是,最好的存储选项是字符串,而不是每次都测试它以查看它是字符串,整数还是浮点数(但是如果我错了,请更正我)。可以以任何方式将字符串配对(例如,允许成对重复)

我将以20个为例:

  
      
  1. 12 13
  2.   
  3. 13 14
  4.   

让我们使用字母来表示它们A,B,C和D,这样我们就不会忽略它们是字符串的事实并了解它们之间的比较。 A = 12,B = 13,C = 14 ...在此示例中,没有D,但可能有其他D。

  
      
  1. AB
  2.   
  3. BC
  4.   

现在我们看到了,我们可以推断出10种可能的匹配方式,以及3种可能不会匹配的方式...并且根据它们的共享方式,从字典中返回7个值之一,集合或索引,数组等。

  
      
  1. AA AA(共享两个都获得索引值1)
  2.   
  3. AA AB(共享1双重获得索引值2)
  4.   
  5. AA BA(共享1双重获得索引值2)
  6.   
  7. AB AA(共享1st双重获得索引值2)
  8.   
  9. AB BB(第二股双倍获得指数值3)
  10.   
  11. AB AB(份额2获得索引值4)
  12.   
  13. AB AC(一次共享一次获得索引值5)
  14.   
  15. AB CA(一次共享一次获得索引值5)
  16.   
     

9。 AB BC(第二次共享获得索引值6)

     
      
  1. AB CB(第二次共享获得索引值6)
  2.   
  3. AA BC(不共享,索引值为7)
  4.   
  5. AB CD(共享不获得索引值7)
  6.   
  7. AB CC(不共享,将获得索引值7)
  8.   

在上面的12,13和13,14的示例中,列表中的数字9是比较结果,我需要获取索引值为6。

撇开我如何获取索引值或这些集合如何出现,我想着重于确定返回哪个索引值的逻辑。我尝试了一个大型嵌套的If-Ifelse,而且运行速度非常慢(进行500k比较时,大约需要7个小时)。我想下一步就是做一个嵌套的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

再次...异常缓慢。我已经尝试过通过将字符串分别存储在数组,字典,类对象中并对其进行迭代来尝试优化比较而无济于事的方法。我认为我已将这个问题归结为是造成问题的原因。不要误会我的意思。对于1组20,它的闪电速度很快,但是当我需要做50,000次时,它需要7个小时。

我还没有尝试过但有一点兴趣的是外部vbscript或C ++多线程代码进行比较(我对vbscipt C ++或多线程一无所知,所以目前这是毫无疑问的。那怎么办?关于如何加快比较的任何建议?

2 个答案:

答案 0 :(得分:1)

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

在测试中,在不到2秒的时间内运行了500.000次迭代。这将取决于您如何读取所有字符串而增加,但是比较本身不是问题。

您将需要对脚本库的引用

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

答案 1 :(得分:0)

我之所以仅发布此内容,是因为我早些时候说过。我向数据库管理员论坛提出了问题,并在提出一些建议后回答了我自己的问题。我很满足于@FunThomas的回答,因为他至少回答了我当时正在寻找的内容,并希望它能对其他人有所帮助。但是,我已经解决了使用三个表,一组派生表和一堆联接进行二进制比较的问题。 5秒内进行67,000次比较。我确定我可以使用更多索引并优化sql和任何前端代码来加快速度。感谢您的所有帮助!

https://dba.stackexchange.com/questions/231866/comparing-two-pairs-of-columns-between-two-tables-and-returning-the-column-from/232370#232370

我将其移回一点以编辑帖子。我只是希望那些随后关注的人能看到他们。