返回列表 上一主題 發帖

[發問] 最快速的比對資料方式?

[發問] 最快速的比對資料方式?

本帖最後由 PKKO 於 2015-9-4 16:34 編輯

小弟的比對資料以A欄位有兩萬筆資料然後比對B欄位的兩萬筆資料,作為範例資料

以前一直以為使用陣列做比對資料,一定是最快的,這是下方的程式碼
  1. Sub test_B()
  2. t1 = Hour(Now()) * 3600 + Minute(Now()) * 60 + Second(Now())

  3. Rng = [a1].Resize(20000, 1).Value
  4. rng2 = [b1].Resize(20000, 1).Value
  5. For j = 1 To 20000
  6.     For i = 1 To 10000
  7.         If Rng(i, 1) = rng2(j, 1) Then
  8.             '找到比對資料就跳開
  9.             Exit For
  10.         End If
  11.     Next
  12. Next
  13. T2 = Hour(Now()) * 3600 + Minute(Now()) * 60 + Second(Now())
  14. MsgBox "共耗時 " & T2 - t1 & " 秒"

  15. End Sub
複製代碼
後來才發現原來,下面的方式更快,但需要注意的重點是match的比對陣列,不可真的放置陣列,速度會比上方慢,且有65536列的限制,但使用範圍做比對,會比上方快450 %....
  1. Sub test_A()
  2. t1 = Hour(Now()) * 3600 + Minute(Now()) * 60 + Second(Now())

  3. rng2 = [b1].Resize(20000, 1).Value
  4. For i = 1 To 20000
  5.     Application.Match(rng2(i, 1), Sheets("test").Range("A:A"), 0)
  6. Next
  7. T2 = Hour(Now()) * 3600 + Minute(Now()) * 60 + Second(Now())
  8. MsgBox "共耗時 " & T2 - t1 & " 秒"
  9. End Sub
複製代碼
小弟不才,想請問各位高手大大,還有更快的比對方式嗎?
PKKO

看您的陣列比對,分明是讓賽一萬倍,給比下來不足為奇,再者您的match 比對在那裡?
ikboy 發表於 2015-9-4 18:11



    大大您好,小弟若是要抓資料的時候,比對程式碼為Application.VLookup(rng2(i, 1), Sheets("test").Range("A:c"), 3, 0) 的方式

這種方式也是比我原本的陣列方式快很多倍

想請問大大為何說我的陣列比對方式是讓賽一萬倍?

您有何種方式可以更快嗎?還請指教~
PKKO

TOP

C.D欄為被比對資料,
根據A欄數據,取出與C欄相同值所對應D欄數值,並填至B欄(與VLOOKUP相同):  ...
准提部林 發表於 2015-9-4 19:50



大大厲害!

您的程式碼小弟承接了

這是我看過最快的方式了

我用傳統的比對方式要35秒(大約),Vlookup的方式要5秒

您的方式只需要0.1x秒,速度上快了將近50倍....太威了

小弟想請教一下,您舉的例子是A 欄比對 C  ,然後取出D

若將題目改A 比對C ,然後得到D,再用D去比對F然後取出G,最後才將G 輸入到B 欄位的話
下方是我用您的方式寫出來的,不曉得如果是大大您本人來撰寫的話,也是會用相同的方式嗎?
還是會用不同的寫法?(更便利or更清楚or更快)
麻煩大大了,大大您的這段程式碼,震撼到小弟了,附檔的部分,會再花時間看,有問題再向大大您請教哦!
  1. Sub TEST_Vlookup()
  2. 'C.D欄為被比對資料,
  3. '根據A欄數據 , 取出與C欄相同值所對應D欄數值, 並填至B欄(與VLOOKUP相同):

  4. Dim TM, Arr, Brr, xRow&, xD, i&
  5. TM = Timer
  6. [B:B].Clear: [J1] = ""
  7. xRow = 20000
  8. Arr = [A1].Resize(xRow)
  9. Brr = [C1:D1].Resize(xRow)
  10. Crr = [f1:g1].Resize(xRow)
  11. Set xD = CreateObject("Scripting.Dictionary")
  12. 'C的D
  13. For i = 1 To UBound(Brr)
  14.     xD(Brr(i, 1)) = Brr(i, 2)
  15. Next
  16. '比對結果得到D
  17. For i = 1 To UBound(Arr)
  18.     Arr(i, 1) = xD(Arr(i, 1))
  19. Next
  20. '多加了part1-----------------------(F的G)
  21. For i = 1 To UBound(Arr)
  22.     xD(Crr(i, 1)) = Crr(i, 2)
  23. Next
  24. '多加了part2-----------------------(比對結果得到G)
  25. For i = 1 To UBound(Arr)
  26.     Arr(i, 1) = xD(Arr(i, 1))
  27. Next


  28. [B1].Resize(xRow) = Arr
  29. [J1] = Timer - TM
  30. End Sub
複製代碼
PKKO

TOP

回復  PKKO


之前你自己不是秀過一段程式碼
你自己裡面就用字典在搜尋
bobomi 發表於 2015-9-4 23:06


有哦!
  1. '宣告物件
  2. Dim D As Object
  3. Set D = CreateObject("SCRIPTING.DICTIONARY")  '字典物件
  4. '判定是否存在於物件之內
  5. If not D.Exists(cstr(E)) Then
  6.         D.Add cstr(E), I
  7. END IF
  8. Ar=d.keys
  9. '移除物件內的所有物件
  10.    'D.RemoveAll
複製代碼
但我不曉得原來字典物件還可以有那樣的用法,我只會這種而已
但他那種方式感覺比我這種好用,就連我上述的程式碼,應該也可以改為他的方式(還沒測試過速度差異)
因為不用跑比對的迴圈,只要跑一次本身,感覺速度快很多
PKKO

TOP

回復 9# 准提部林


    謝謝版主大大,您的程式碼真的很不錯,小弟可否再向版大請教一下

傳統的方式for i 到 for j 的方式 我可以使用 like 來 找出相關文字
ex:
m=0
rng=[a1].currentregion
for i = 1 to ubound(rng)
     for j = 1 to ubound(rng,2)
          if rng(i,j) like "*" & "AA" & "*" then
               m=m+1
          endif
     next
next

那用大大您的陣列+字典的方式呢?要如何辦到?
因為大大您的方式很快速,但目前卡在這邊還請大大指導一下!
PKKO

TOP

        靜思自在 : 口說好話、心想好意、身行好事。
返回列表 上一主題