So sánh tốc độ khi add các loại dữ liệu khác nhau vào dictionary (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Mon_Lon_Ton

Thành viên mới
Tham gia
5/9/17
Bài viết
13
Được thích
2
Giới tính
Nam
Xin chào toàn thể anh chị em trong diễn đàn.
Mình có một thắc mắc mà tìm hiểu mãi không có kết quả.
Số là mình add key vào dictionary với số lượng khoảng 60.000 key (là customer id - có 10 số trong báo cáo load từ hệ thống) dưới dạng number thì mất khoảng 2 phút. Tuy nhiên cũng số lượng key tương tự, mình load từ báo cáo khác dưới dạng text thì add vào dictionary chỉ mất khoảng 0.3 giây.
Anh chị em cho mình hỏi tại sao lại có sự khác biệt quá lớn như vậy giữa text và number khi add vào dictiionary?
Và có cách nào chuyển number thành text trong array sau đó in ra bảng tính mà vẫn giữ được thuộc tính text hay không?
Trân trọng cảm ơn!
 
chuyển number thành text trong array
Mã:
Sub vidu_a()
    Dim Dic As Object
    Set Dic = CreateObject("Scripting.Dictionary")
    Dim x As Long, y As Long, i As Long, sKey As String, Rng As Range
    x = 1000000000
    y = 1000060000
    For i = x To y
        sKey = CStr(i)
        If Dic.Exists(sKey) = False Then
            Dic.Add sKey, ""
        End If
    Next i
'    If Dic.Count > 1 Then Rng.Value = Application.Transpose(Dic.keys)
End Sub
in ra bảng tính mà vẫn giữ được thuộc tính text
Định dạng vùng ở bảng tính sẵn là kiểu "Text".
 
Upvote 0
@befaint:
Number có 2 dạng, dạng float và dạng integer. Nguyên tắc chung là làm việc với dạng integer nhanh hơn dạng float nhiều.
Muốn cụ thể, bạn phải biết dữ liệu của ngừoi ta nói là dạng nào.

(vả lại, cái này đâu phải là "Học tập online". Đối với tôi, ngừoi khong biết phân biệt góc để hỏi bài thì dữ liệu của họ khó tin cậy - vài giây nói thành vài phút ai biết đâu mà lường)
 
Upvote 0
Cảm ơn mọi người đã nhiệt tình chia sẻ.
Vì là lần đầu tiên tham gia diễn đàn nên mình chưa đưa thắc mắc vào đúng box, mong mọi người thông cảm. Nếu admin có đọc được bài này xin phiền bạn chuyển qua box phù hợp giúp mình.
Quay trở lại câu hỏi, mình có file test đính kèm, nếu add vào dic dưới dạng số (sheet Number) thì mất khoảng 120 giây, trong khi dữ liệu đã được chuyển qua dạng text (sheet text) thì add chỉ mất 0.5 giây.
befaint
VetMini

giúp mình với nhé.
Thanks mọi người.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Sub vidu_a() Dim Dic As Object Set Dic = CreateObject("Scripting.Dictionary") Dim x As Long, y As Long, i As Long, sKey As String, Rng As Range x = 1000000000 y = 1000060000 For i = x To y sKey = CStr(i) If Dic.Exists(sKey) = False Then Dic.Add sKey, "" End If Next i ' If Dic.Count > 1 Then Rng.Value = Application.Transpose(Dic.keys) End Sub
Cảm on befaint đã chia sẻ. Mình đã viết lại code theo hướng dẫn của bạn nhưng sau khi in dữ liệu từ mảng ra cell, so sánh với keys của dic thì vấn không khớp. Có vẻ như dic vẫn hiểu dữ liệu trong các cell được in ra từ mảng là định dạng number chứ không phải text. Nếu thay đoạn code: Cells(i, 3) = dic.Item(Cells(i, 2)) trong sheet "Number" thành Cells(i, 3) = dic.Item(Cstr(Cells(i, 2))) thì kết quả rất nhanh và chuẩn. befaint kiểm tra sheet "Number" trong file đính kèm và giải thích giúp mình với đc ko?
 

File đính kèm

Upvote 0
Cảm on befaint đã chia sẻ. Mình đã viết lại code theo hướng dẫn của bạn nhưng sau khi in dữ liệu từ mảng ra cell, so sánh với keys của dic thì vấn không khớp. Có vẻ như dic vẫn hiểu dữ liệu trong các cell được in ra từ mảng là định dạng number chứ không phải text. Nếu thay đoạn code: Cells(i, 3) = dic.Item(Cells(i, 2)) trong sheet "Number" thành Cells(i, 3) = dic.Item(Cstr(Cells(i, 2))) thì kết quả rất nhanh và chuẩn. befaint kiểm tra sheet "Number" trong file đính kèm và giải thích giúp mình với đc ko?
PHP:
Sub TestNum()
Dim Ts As Double
Ts = Timer
Dim arr(), dic As Object, lRow As Long, i As Long, sKey As String
Set dic = CreateObject("scripting.dictionary")
With Sheet1
    lRow = .Range("A" & Rows.Count).End(xlUp).Row
    If lRow < 2 Then Exit Sub
    arr = .Range("A2:A" & lRow)
    'MsgBox TypeName(arr(1, 1)) 'Double
    For i = 1 To UBound(arr, 1)
        'sKey = CStr(arr(i, 1))'
        sKey = "'" & arr(i, 1)
        If dic.exists(sKey) = False Then dic.Add (sKey), ""
    Next
    If dic.Count > 1 Then
        .Range("B2:B" & lRow).ClearContents
        .Range("B2").Resize(dic.Count, 1) = Application.Transpose(dic.keys)
    End If
End With
MsgBox Round(Timer - Ts, 3) & " giây"
End Sub
'--------------'
Sub TestText()
Dim Ts As Double
Ts = Timer
Dim arr(), dic As Object, lRow As Long, i As Long, sKey As String
Set dic = CreateObject("scripting.dictionary")
With Sheet2
    lRow = .Range("A" & Rows.Count).End(xlUp).Row
    If lRow < 2 Then Exit Sub
    arr = .Range("A2:A" & lRow).Value
    'MsgBox TypeName(arr(1, 1)) 'String
    For i = 1 To UBound(arr, 1)
        'sKey = arr(i, 1)'
        sKey = "'" & arr(i, 1)
        If dic.exists(sKey) = False Then dic.Add (sKey), ""
    Next
    If dic.Count > 1 Then
        .Range("B2:B" & lRow).ClearContents
        .Range("B2").Resize(dic.Count, 1) = Application.Transpose(dic.keys)
    End If
End With
MsgBox Round(Timer - Ts, 3) & " giây"
End Sub
Hỏi: Add từng đó Key vào Dic để làm gì tiếp?
 
Upvote 0
Cảm ơn befaint
Nguyên do của tình huống này là mình tạo 1 dic để vlookup cho nhanh, vì dữ liệu lớn (bảng tham chiếu khoảng 60.000 dòng như file test, dữ liệu cần tham chiếu khoảng 70.000 dòng) nên vlookup trong excel rất chậm.
Tuy nhiên khi add key của dic dưới dạng number thì chậm vô cùng (trước mình chỉ test dữ liệu vài nghìn dòng thì ko cảm nhận được), chuyển sang text thì nhanh hơn rất nhiều, không hiểu tại sao nên lao lên đây hỏi anh chị em ^_^. Có 2 vấn đề mình vẫn chưa được rõ:
- Tại sao add key của dic dưới dạng text lại nhanh hơn dạng number
- Tại sao add key của dic dưới dạng text -> chuyển text trong mảng -> in mảng ra cells -> tham chiếu cells với keys của dic thì không tồn tại (như tình huống mình sử dụng Cstr ở file đính kèm trên).
Rất mong được befaint chỉ giáo
 
Upvote 0
- Tại sao add key của dic dưới dạng text lại nhanh hơn dạng number
Không hiểu sao Dictionary cho Key nhận kiểu dữ liệu là số mà lại chậm khi gặp số to. Cái ni chắc đợi người khác giải đáp.
Tại sao add key của dic dưới dạng text -> chuyển text trong mảng -> in mảng ra cells -> tham chiếu cells với keys của dic thì không tồn tại
Hai kiểu dữ liệu khác nhau thì tìm thấy nhau sao được.
Ví dụ nhập vào C1 là '1 (dấu nháy đơn và số 1), nhập vào D1 là 1 (nhập số 1). Rồi nhập vào E1=C1=D1 xem trả về gì?
Tức là chuỗi "1" <> số 1.
-----
Nếu vẫn dùng "Ac No" là số thì thử đoạn sau:
PHP:
Sub TestNumHashtable()
Dim Ts As Double
Ts = Timer
Dim HTbl As Object
Set HTbl = CreateObject("System.Collections.Hashtable")
Dim arr(), lRow As Long, i As Long, Result(), j As Long, ID
With Sheet1
    lRow = .Range("A" & Rows.Count).End(xlUp).Row
    If lRow < 2 Then Exit Sub
    arr = .Range("A2:A" & lRow)
    lRow = UBound(arr, 1)
    ReDim Result(1 To lRow, 1 To 1)
    For i = 1 To lRow
        ID = arr(i, 1)
        If HTbl.Containskey(ID) = False Then
            HTbl.Add ID, ""
            j = j + 1
            Result(j, 1) = ID
        End If
    Next
    If j > 0 Then
        .Range("B2:B" & lRow).ClearContents
        .Range("B2").Resize(j, 1) = Result
    End If
End With
MsgBox Round(Timer - Ts, 3) & " giây"     '0.7 giây'
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn befaint đã chia sẻ. Mình dùng Cstr như hướng dẫn của bạn trong mảng và đã xử lý được vấn đề rồi.
Còn trường hợp "dictionary add số lớn rất chậm" thì đành chờ các cao thủ khác chỉ giáo ^_^ thôi
 
Upvote 0
Bạn bỏ đoạn này và Test lại sub TestNum
Mã:
For i = 1 To UBound(arr, 1)
    Cells(i, 3) = dic.Item(Cells(i, 2))
Next
------------------------------
Update:

Đã test lại, phần Text cho kết quả nhanh hơn Number nhiều đúng như phần test của bạn.
 
Lần chỉnh sửa cuối:
Upvote 0
Test tốc độ, trừ phi có tiêu chuẩn, kết quả chỉ là chủ quan:

Sub t()
Const NUM1 = 100000
Const NUM2 = 200000
Debug.Print "From "; NUM1; " To: "; NUM2
Set d1 = CreateObject("scripting.dictionary")
Set d2 = CreateObject("scripting.dictionary")
Dim n(1 To 1000000) As Long, a(1 To 1000000) As String
For i = NUM1 To NUM2
n(i) = i * 10 ' để bảo đảm 2 cái có độ dài chuỗi bằng nhau
a(i) = "a" & i
Next i
tim = Timer
For i = NUM1 To NUM2
d1.Add n(i), n(i)
Next i
Debug.Print "Round 1: ", Timer - tim, d1.Count; " items"
tim = Timer
For i = NUM1 To NUM2
d2.Add a(i), a(i)
Next i
Debug.Print "Round 2: ", Timer - tim, d2.Count; " items"
Set d1 = Nothing
Set d2 = Nothing
End Sub

Kết quả (NUM2 là 200000, 500000, và 800000):

From 100000 To: 200000
Round 1: 0.1835938 100001 items
Round 2: 0.3085938 100001 items
From 100000 To: 500000
Round 1: 5.050781 400001 items
Round 2: 5.675781 400001 items
From 100000 To: 800000
Round 1: 16.10938 700001 items
Round 2: 18.51563 700001 items

Kết luận: với cách thử của tôi thì 2 cái gần như nhau. Tôi nghĩ round2 chậm hơn chút xíu cũng có phần do mảng chuỗi truy cập chậm hơn mảng long.

Chú: khả năng của Dic phải xét trên cả tốc độ truy vấn chứ không phải chỉ thêm vào là đủ.
 
Lần chỉnh sửa cuối:
Upvote 0
Không hiểu sao Dictionary cho Key nhận kiểu dữ liệu là số mà lại chậm khi gặp số to. Cái ni chắc đợi người khác giải đáp.

Hai kiểu dữ liệu khác nhau thì tìm thấy nhau sao được.
Ví dụ nhập vào C1 là '1 (dấu nháy đơn và số 1), nhập vào D1 là 1 (nhập số 1). Rồi nhập vào E1=C1=D1 xem trả về gì?
Tức là chuỗi "1" <> số 1.
-----
Nếu vẫn dùng "Ac No" là số thì thử đoạn sau:
PHP:
Sub TestNumHashtable()
Dim Ts As Double
Ts = Timer
Dim HTbl As Object
Set HTbl = CreateObject("System.Collections.Hashtable")
Dim arr(), lRow As Long, i As Long, Result(), j As Long, ID
With Sheet1
    lRow = .Range("A" & Rows.Count).End(xlUp).Row
    If lRow < 2 Then Exit Sub
    arr = .Range("A2:A" & lRow)
    lRow = UBound(arr, 1)
    ReDim Result(1 To lRow, 1 To 1)
    For i = 1 To lRow
        ID = arr(i, 1)
        If HTbl.Containskey(ID) = False Then
            HTbl.Add ID, ""
            j = j + 1
            Result(j, 1) = ID
        End If
    Next
    If j > 0 Then
        .Range("B2:B" & lRow).ClearContents
        .Range("B2").Resize(j, 1) = Result
    End If
End With
MsgBox Round(Timer - Ts, 3) & " giây"     '0.7 giây'
End Sub
Vậy là Mạnh học thêm 1 cách xài Hashtable .............. Nó cũng không khó lắm nhỉ ........... :D

Không biết có xài được cho Office 2003 To 2016 không biết ?! .... và nó cần .NET Mấy Chấm trở lên mới xài ok và nếu WindowsXP không có NET thì điều gì sẻ xẩy ra ??!!
 
Lần chỉnh sửa cuối:
Upvote 0
Vậy là Mạnh học thêm 1 cách xài Hashtable .............. Nó cũng không khó lắm nhỉ ...........
Khó nhất lúc tìm tài liệu đó anh. Không biết nó có thuộc tính, phương thức gì. Không như thèng Dictionary ,dù khai báo sớm nó cũng không hiện ra cái Tooltip... :(
Hashtable có 2 phương thức ContainsKey và ContainsValue, không biết có thể áp dụng thay cho bài nào xài 2 Dic không...
Không biết có xài được cho Office 2003 To 2016 không biết ?! .... và nó cần .NET Mấy Chấm trở lên mới xài ok và nếu WindowsXP không có NET thì điều gì sẻ xẩy ra ??!!
Có một anh ở trên chuột bạch rồi đó anh. :D :D
 
Upvote 0
Vậy là Mạnh học thêm 1 cách xài Hashtable .............. Nó cũng không khó lắm nhỉ ........... :D

Không biết có xài được cho Office 2003 To 2016 không biết ?! .... và nó cần .NET Mấy Chấm trở lên mới xài ok và nếu WindowsXP không có NET thì điều gì sẻ xẩy ra ??!!

Mấy chấm cũng được. Hashtable là căn bản của mọi nền tảng phát triển phần mềm (sofware platform).
Không có .Net thì lấy đâu ra thư viện "System.Collections". Nếu máy có cái khác thì cứ việc cho vào.
Ở vài nói về Hastbale, tôi có giải thích rằng các nền tảng khong nhất thiết giống nhau cho nên chưa chắc chúng phù hợp với nhau. Và vì vậy, các ứng dụng sử dụng thư viện của .Net nên cẩn thận.
 
Upvote 0
Khó nhất lúc tìm tài liệu đó anh. Không biết nó có thuộc tính, phương thức gì. Không như thèng Dictionary ,dù khai báo sớm nó cũng không hiện ra cái Tooltip... :(
Hashtable có 2 phương thức ContainsKey và ContainsValue, không biết có thể áp dụng thay cho bài nào xài 2 Dic không...

Có một anh ở trên chuột bạch rồi đó anh. :D :D
chính xác đó ... lập trình quan trọng nhất là khai phá sử dụng nó .............. nếu ko có những bước đi khởi đầu đó thì làm sao có những bước đi kế tiếp hay

Có lần Mạnh nhớ Anh @batman1 có nêu ra ý tương tự như vậy ........................
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom