Dictionary & Collection ?

Liên hệ QC

Hoàng Nhật Phương

Thành viên gắn bó
Tham gia
5/11/15
Bài viết
1,894
Được thích
1,214
Xin chào các Bạn,
Đầu xuân chúc mọi người luôn mạnh khỏe & bình an.
----
Như tiêu đề OT đã nêu, OT có đọc bài viết của Bạn Collection @befaint nhưng có lẽ do kiến thức còn hạn hẹp nên chưa thể hiểu hết về sự khác biệt giữa Dictionary & Collection,
Ví dụ trong 2 đoạn code dưới đây sử dụng Dictionary & Collection cho cùng một công việc:
Mã:
Option Explicit

Sub CollectionFilter()
Dim TT As Double
TT = Timer
Dim myCol As Collection
Set myCol = New Collection
Dim i As Long, lRow As Long, ArrData(), Result(), sKey As String, j As Long
With Sheet1
    lRow = .Range("B" & Rows.Count).End(xlUp).Row
    ArrData = .Range("B2:D" & lRow).Value2
    lRow = UBound(ArrData, 1)
    ReDim Result(1 To lRow, 1 To 4)
    For i = 1 To lRow
        sKey = ArrData(i, 1)
        If sKey <> "" Then
            If KeyExists(myCol, sKey) = False Then
                j = j + 1
                myCol.Add j, sKey
                Result(j, 1) = j
                Result(j, 2) = sKey
                Result(j, 3) = ArrData(i, 2)
                Result(j, 4) = ArrData(i, 3)
            Else
                Result(myCol.Item(sKey), 4) = Result(myCol.Item(sKey), 4) + ArrData(i, 3)
             End If
        End If
    Next i
    If j > 0 Then
        .Range("M2").Resize(100, 4).ClearContents
        .Range("M2").Resize(j, 4) = Result
        .Range("Q7") = Timer - TT
    End If
End With


End Sub


Sub DictionaryFilter()
Dim TT As Double
TT = Timer

Dim Dic As Object
Dim i As Long, lRow As Long, ArrData(), Result(), sKey As String, j As Long
Set Dic = CreateObject("Scripting.Dictionary")
With Sheet1
    lRow = .Range("B" & Rows.Count).End(xlUp).Row
    ArrData = .Range("B2:D" & lRow).Value2
    lRow = UBound(ArrData, 1)
    ReDim Result(1 To lRow, 1 To 4)
    For i = 1 To lRow
        sKey = ArrData(i, 1)
        If sKey <> "" Then
            If Not Dic.Exists(sKey) Then
                j = j + 1
                Dic.Add sKey, j
                Result(j, 1) = j
                Result(j, 2) = sKey
                Result(j, 3) = ArrData(i, 2)
                Result(j, 4) = ArrData(i, 3)
            Else
                Result(Dic.Item(sKey), 4) = Result(Dic.Item(sKey), 4) + ArrData(i, 3)
            End If
        End If
    Next i
    If j > 0 Then
        .Range("H2").Resize(100, 4).ClearContents
        .Range("H2").Resize(j, 4) = Result
        .Range("L7") = Timer - TT
    End If
End With

End Sub
Trên máy tính của OT có vẻ như Collection nhanh hơn Dictionary :
1613618736712.png

Nhờ các bạn chỉ dẫn cho OT hiểu rõ thêm trong trường hợp nào thì dùng cái nào sẽ tối ưu hơn?
Tại sao Collection nhanh hơn Dictionary mà không thấy mọi người sử dụng Collection mà thường sử dụng Dictionary hơn hay do thói quen ạ?
 

File đính kèm

  • Collection.xlsb
    1.2 MB · Đọc: 13
Lần chỉnh sửa cuối:
Tôi nghĩ là độ dài key cũng không đáng ngại. Cái quan trọng là có tất cả bao nhiêu dữ liệu (key) và trong đó số key duy nhất là bao nhiêu.

Như trong bài #5 ta có:
Mã:
Private Const maxCount = 1048500
Private Const prefixKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
...
For i = 1 To maxCount
    sKey = prefixKey & i
Tức hơn 1 triệu key và cũng là hơn 1 triệu key duy nhất, có độ dài từ 28 (i = 1..9) tới 34 ký tự. Bài toán với hơn 1 triệu key duy nhất tôi thấy có vẻ ít gặp trong cuộc sống văn phòng. Nếu ta sửa thành sKey = prefixKey & (i Mod 100000), tức hơn 1 triệu key nhưng số key duy nhất là 100 000, và vẫn độ dài ấy thì có lẽ đít thon ít mỡ sẽ cho collection biết thế nào là lễ độ.

Mọi người thử xem sao nhé.
Khả năng của ai có thể viết Hàm Tự tạo được như mô tả của bài này mà Nhanh hơn Dic của Bill thì viết ... Còn ko viết được thì cứ Dic của Bill lôi ra mà xài cho nhanh
 
Upvote 0
Upvote 0
Upvote 0
Tôi xin chịu ...
... tìm ai đó trên GPE này mà mấy năm nay lâu lâu lại nói tới thuật ngữ Bảng Băm ấy ..
Hic, cảm ơn Bạn đã cho OT biết.. nếu Bạn mà chịu thì OT đến mùa nào,mà ai vậy cứ nghe thấy Băm chém là OT thấy hãi quá, Ot chỉ đọc nhiều bài liên quan đến chủ đề của OT thôi ạ.. nhưng dù 'Cây cổ thủ' nào chăng nữa thì tạm thời OT cũng xin phép dừng vấn đề này ở đây ạ kẻo lại sang chủ đề khác ạ (nếu ai đó mà bạn nói tới có thể chỉ cho OT vấn đề này để OT làm được thì xin xui lòng chuyển qua chủ đề bên đó ạ).
 
Upvote 0
Băm với biếc. Quên đi.
Thuật toán dựng các cấu trúc hổ trợ cách search index table phức tạp bỏ bố. Cái giản dị nhất trong bọn là search cây nhị phân, số người có khả năng hiểu trên diễn đàn này đếm được trên đầu ngón tay.
 
Upvote 0
Code này chạy nhanh nè, thử 5000 key tôi cảm thấy chạy rất ngọt ngào, khi nhìn code thấy .listindex tôi không nghĩ code có thể chạy mượt như vậy, và khi năng lên 10000 key thì tôi cảm thấy nó không mượt mà như trước nữa. Code này có điểm cộng lớn, nếu hiểu bản chất mà trau truốt thêm tôi nghĩ sẽ rất tiềm năng.
Trong cái bài đó mình khuyến mãi thêm cái cột thứ 2 là cộng dồn (có thể là chuỗi, cũng có thể là số) các giá trị ở cột 2, nếu không, chỉ đơn giản là lọc duy nhất 1 cột thì có lẽ nó cũng không phải chậm lắm đâu. Và dùng combobox cũng có thể remove 1 item hoặc tất cả.
 
Upvote 0
.. Nếu ta sửa thành sKey = prefixKey & (i Mod 100000), tức hơn 1 triệu key nhưng số key duy nhất là 100 000, và vẫn độ dài ấy thì có lẽ đít thon ít mỡ sẽ cho collection biết thế nào là lễ độ.
Dạ, Bác thực sự là mới năm ngoái con thường làm việc với dữ liệu trong Database nên dữ liệu nhiều vô kể thậm trí có lúc copy ra Excel để sử dụng VBA nhưng Excel không đủ sức chứa nó vì thế mà con đã tìm đến ngôn ngữ SQL để xử lý,dữ liệu sau khi đổ xuống Excel gần như gọi là báo cáo đã được rút gọn đi rất rất Bác ạ, và có lẽ số key duy nhất cũng không thể vượt con số 100,000 (với dữ liệu con hay dùng có lẽ lớn nhất vẫn là báo thẻ kho từ thời điểm đến thời điểm).
(với dữ liệu lớn này chỉ có dùng phần mềm là nhanh nhưng phần mềm thì lại có những hạn chế không theo ý muốn mà theo ýthì lại phải mất phí chính vì vậy mà nếu có thể sử dụng được các câu lệnh truy vấn được thì con thấy vẫn là chủ động nhất ạ.)
Có cái khác 'ngon' hơn thế nữa là đằng khác.
Chuyện thử nghiệm phải phân định các trường hợp của dữ liệu đầu vào để thử nghiệm:
- Add nhiều lần 1 key <--- thử nghiệm phần kiểm tra sự tồn tại key trong object;
- Add nhiều keys không trùng lần nào <--- kiểm tra Add key vào object;
- Add nhiều keys có tỉ lệ trùng 30-50-90%... <--- trường hợp hỗn hợp.
- Còn trường hợp kiểu dữ liệu của key: Number, String. Cái này Dictionary còn mệt nữa.

Việc Add key là công việc rất nặng nề, sau một thời gian thử nghiệm thấy Dictionary rất đuối.
Với 'Hashtable' OT có biết đến qua những lần Bạn sử dụng nhưng OT cũng chưa đọc kỹ và để ý đến nó, mới so sánh công cụ này với Dic và Col trong tập tin bạn gửi thì lại hơn hẳn.
Hình như cái này đòi hỏi phải cài thêm gì đó (OT nhớ không rõ) vì có lần lâu lắm rồi khi chạy code bị lỗi OT phải cài gì đó hay là sửa sang Dic thì phải.
Cảm ơn Bạn đã cho OT thêm cách này để so sánh, nhìn cách dùng nó cũng tương tự với cách dùng Dic lắm (tự nhiên nổi máu tham muốn như muốn mở rộng chủ đề để quá hihi chết mất). -\\/.
 
Upvote 0
Dạ, Bác thực sự là mới năm ngoái con thường làm việc với dữ liệu trong Database nên dữ liệu nhiều vô kể thậm trí có lúc copy ra Excel để sử dụng VBA nhưng Excel không đủ sức chứa nó vì thế mà con đã tìm đến ngôn ngữ SQL để xử lý,dữ liệu sau khi đổ xuống Excel gần như gọi là báo cáo đã được rút gọn đi rất rất Bác ạ, và có lẽ số key duy nhất cũng không thể vượt con số 100,000 (với dữ liệu con hay dùng có lẽ lớn nhất vẫn là báo thẻ kho từ thời điểm đến thời điểm).
(với dữ liệu lớn này chỉ có dùng phần mềm là nhanh nhưng phần mềm thì lại có những hạn chế không theo ý muốn mà theo ýthì lại phải mất phí chính vì vậy mà nếu có thể sử dụng được các câu lệnh truy vấn được thì con thấy vẫn là chủ động nhất ạ.)
Bởi bạn chú ý đến tốc độ mà ví dụ kết luận là đít sần đuối nên tôi có lưu ý thôi.

Trong bài #5 có hơn 1 triệu key và đó cũng là hơn 1 triệu key DUY NHẤT. Kết luận là đít sần "tê" đến mức không lê nổi. Tôi chỉ muốn lưu ý là cũng dữ liệu khủng đó nhưng nếu lượng key DUY NHẤT khác thì tình hình lại khác. Và tôi muốn lưu ý nữa là bài toán nào sát thực tế hơn.
1. Trong công việc thực tế hàng ngày số lần bạn gặp hơn 1 triệu key DUY NHẤT là bao nhiêu lần?
2. Nếu số key DUY NHẤT là khoảng 100 000 thì bạn chỉ cần sửa như tôi hướng dẫn thì bạn cũng sẽ thấy là cũng với dữ liệu khủng 1 triệu key nhưng số key DUY NHẤT là 100 000 thì bây giờ đít sần lại phi như bay về đích. Bạn đã thử như tôi hướng dẫn chưa, kết quả thế nào? Bạn không cho biết cụ thể.

Do bạn cứ nghĩ là collection hoặc đít sần nhanh hơn nên mục đích của tôi chỉ là chỉ ra các trường hợp cụ thể, khi mà collection hoặc đít sần nhanh hơn. Tùy lượng dữ liệu, số key duy nhất, và mục đích cần tính gì mà chọn phương pháp, công cụ thôi bạn ạ. Bạn hãy học cách sử dụng mọi công cụ có trong xưởng, còn dùng cái nào thì tùy vào công việc cụ thể. Hôm nay cần đào cái rãnh nhỏ trong vườn thì dùng xẻng thôi. Ngày mai cần đào móng thì dùng máy đào máy xúc.
 
Upvote 0
(với dữ liệu lớn này chỉ có dùng phần mềm là nhanh nhưng phần mềm thì lại có những hạn chế không theo ý muốn mà theo ýthì lại phải mất phí chính vì vậy mà nếu có thể sử dụng được các câu lệnh truy vấn được thì con thấy vẫn là chủ động nhất ạ.)
Theo mình thấy có gì đó sai sai, mình không biết bạn làm bộ phận gì mà nghĩ sợ công ty mất phí....(có phải tiền bạn đâu nhỉ ??? Hay bạn muốn thể hiện để ...)
Nếu vậy bạn tự nhiên cứu đi, có thực mới giật được đạo chứ nhỉ
 
Upvote 0
Bởi bạn chú ý đến tốc độ mà ví dụ kết luận là đít sần đuối nên tôi có lưu ý thôi.

Trong bài #5 có hơn 1 triệu key và đó cũng là hơn 1 triệu key DUY NHẤT. Kết luận là đít sần "tê" đến mức không lê nổi. Tôi chỉ muốn lưu ý là cũng dữ liệu khủng đó nhưng nếu lượng key DUY NHẤT khác thì tình hình lại khác. Và tôi muốn lưu ý nữa là bài toán nào sát thực tế hơn.
1. Trong công việc thực tế hàng ngày số lần bạn gặp hơn 1 triệu key DUY NHẤT là bao nhiêu lần?
2. Nếu số key DUY NHẤT là khoảng 100 000 thì bạn chỉ cần sửa như tôi hướng dẫn thì bạn cũng sẽ thấy là cũng với dữ liệu khủng 1 triệu key nhưng số key DUY NHẤT là 100 000 thì bây giờ đít sần lại phi như bay về đích. Bạn đã thử như tôi hướng dẫn chưa, kết quả thế nào? Bạn không cho biết cụ thể.

Do bạn cứ nghĩ là collection hoặc đít sần nhanh hơn nên mục đích của tôi chỉ là chỉ ra các trường hợp cụ thể, khi mà collection hoặc đít sần nhanh hơn. Tùy lượng dữ liệu, số key duy nhất, và mục đích cần tính gì mà chọn phương pháp, công cụ thôi bạn ạ. Bạn hãy học cách sử dụng mọi công cụ có trong xưởng, còn dùng cái nào thì tùy vào công việc cụ thể. Hôm nay cần đào cái rãnh nhỏ trong vườn thì dùng xẻng thôi. Ngày mai cần đào móng thì dùng máy đào máy xúc.
Dạ vâng Bác, con cảm ơn Bác nhiều ạ.

Đọc lại bài 45, code chạy sẵn và so sánh sẵn
Trời ạ, tại Chú hôm nay hỏi con nhiều mà đi đường con quá cả lối về nhà một đoạn dài, giờ con mới về đến nhà đây. Hic
Bài đã được tự động gộp:

Theo mình thấy có gì đó sai sai, mình không biết bạn làm bộ phận gì mà nghĩ sợ công ty mất phí....(có phải tiền bạn đâu nhỉ ??? Hay bạn muốn thể hiện để ...)
Nếu vậy bạn tự nhiên cứu đi, có thực mới giật được đạo chứ nhỉ
Cảm ơn bạn đã quan tâm, thực ra OT chỉ làm nhân viên thống kê thôi nhưng do cả một quá trình hoạt động cải tiến của công ty với bản tính cứ đâu là bon chen nên nó đến giờ mọi việc nó trở nên như vậy đó thực ra chỉ cũng chỉ là đa mê công việc thôi.. vấn đề này cũng nhiều người hỏi OT trên GPE này rồi có thể bạn không để ý nên không biết thôi, vài lởi là vậy.
Công ty OT nghèo lắm bạn ạ, mua được phần mềm là một sự cố gắng rồi.
Chỉ là vài lời chia sẻ lại thôi mong bạn cũng đừng để ý thêm để ảnh hưởng đến vấn đề ngoài lề ạ.
 
Lần chỉnh sửa cuối:
Upvote 0
Dạ vâng Bác, con cảm ơn Bác nhiều ạ.


Trời ạ, tại Chú hôm nay hỏi con nhiều mà đi đường con quá cả lối về nhà một đoạn dài, giờ con mới về đến nhà đây. Hic
Bài đã được tự động gộp:


Cảm ơn bạn đã quan tâm, thực ra OT chỉ làm nhân viên thống kê thôi nhưng do cả một quá trình hoạt động cải tiến của công ty với bản tính cứ đâu là bon chen nên nó đến giờ mọi việc nó trở nên như vậy đó thực ra chỉ cũng chỉ là đa mê công việc thôi.. vấn đề này cũng nhiều người hỏi OT trên GPE này rồi có thể bạn không để ý nên không biết thôi, vài lởi là vậy.
Công ty OT nghèo lắm bạn ạ, mua được phần mềm là một sự cố gắng rồi.
Chỉ là vài lời chia sẻ lại thôi mong bạn cũng đừng để ý thêm để ảnh hưởng đến vấn đề ngoài lề ạ.
Hihi bởi vậy mình mới nói mình cảm thấy "sai sai". Theo ý kiến cá nhân của mình thì không phải tiền của mình thì mình sẽ cố gắng lấy quyền lợi về người lao động cao nhất có thể, nhất là những người có nhiệt huyết với công ty, mình xin lỗi làm lạc đề của chủ đề.
Mình xin stop tại đây
 
Upvote 0
Hihi bởi vậy mình mới nói mình cảm thấy "sai sai". Theo ý kiến cá nhân của mình thì không phải tiền của mình thì mình sẽ cố gắng lấy quyền lợi về người lao động cao nhất có thể, nhất là những người có nhiệt huyết với công ty, mình xin lỗi làm lạc đề của chủ đề.
Mình xin stop tại đây
Không sao Bạn, năm ngoái có thời điểm OT còn được anh @Hai Lúa Miền Tây teamviewer tại máy trong cơ quan để xử lý vấn đề liên quan đến SQL và xem Anh code và hướng dẫn mất hàng giờ đến giờ OT vẫn còn ấn tượng, và rất nhiều người OT còn mang ơn để OT có ngày hôm nay mà không có cơ hội để đáp lại .. hihi tâm trạng nên viết thêm một chút OT cũng dừng vấn đề riêng tư của OT ạ.
 
Upvote 0
(*2) tuy bạn thường thấy đít sần cũng cho ra thứ tự nhập như vậy, nhưng MS không hề bảo đảm việc này cho đít sần, dựa vào đó mà viết code thì chết có ngày.
Vậy cái dụ application.transpose(dic.keys) và application.transpose(dic.items) có đảm bảo luôn khớp nhau không bác?
 
Upvote 0
Trong chăn mới biết có nhóc gì. :)
Câu chuyện dữ liệu lớn và lớn, dùng Excel/ Google sheets giờ đây phổ biến rồi.
Xin chào @befaint
OT không thể đem dữ liệu thực cứ vậy mà gửi lên được Bạn (dữ liệu nhiều, không hẳn nói lên được việc kinh doanh phát triển lợi nhuận có). Bạn nói rất đúng trong chăn mới biết,đôi khi muốn hỏi hơn nữa nhưng OT không thể.. vì hỏi nữa OT sẽ phải xác nhận rất nhiều thậm trí phải qua cấp trên xác nhận,bản thân, công ty thậm trí khách hàng..mong bạn thông cảm, câu nói dữ liệu lớn mờ nhạt OT không muốn mọi người để ý vì trích dẫn chỉ riêng với Bác Siwtom (@batmnat1) thôi bởi cả một quá trình từ thơ dại đến lúc này của OT Bác ấy cũng đã dành thời gian không ít cho OT trên GPE này ...
 
Lần chỉnh sửa cuối:
Upvote 0
Vậy cái dụ application.transpose(dic.keys) và application.transpose(dic.items) có đảm bảo luôn khớp nhau không bác?
keys là một hàm trả về một mảng, items cũng vậy.
Trả lời theo đoán mò (không có tài liệu, dùng thống kê để đoán):
Người ta vẫn hay coi như chúng song song thì chắc là 2 cái mảng ấy nó đi cặp với nhau.
Nhưng vì không thấy MS nói gì về điều này, bảo đảm 100% thì chưa dám.
Nói cách khác, đánh cược hai ăn một thì tôi cược, nhưng 10 ăn một thì chờ tìm tài liệu hoặc kiếm được thằng bạn nào đó để hỏi.

Thử như vầy:
- lập một cái dic
- add, remove, đổi keys, đổi items nhiều lần
(nếu chỉ add thì chả có gì để tét, phai xoá đổi tùm lum nới hy vọng nó ảnh hưởng đến thứ tự)

chạy code:
For i = 0 To dic.Count - 1
If Dic.Items()(i) <> Dic(Dic.Keys()(i)) Then
Debug.Print "Broken at index = " & i
End If
Next i
 
Upvote 0
Tôi nghĩ là độ dài key cũng không đáng ngại. Cái quan trọng là có tất cả bao nhiêu dữ liệu (key) và trong đó số key duy nhất là bao nhiêu.

Như trong bài #5 ta có:
Mã:
Private Const maxCount = 1048500
Private Const prefixKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
...
For i = 1 To maxCount
    sKey = prefixKey & i
Tức hơn 1 triệu key và cũng là hơn 1 triệu key duy nhất, có độ dài từ 28 (i = 1..9) tới 34 ký tự. Bài toán với hơn 1 triệu key duy nhất tôi thấy có vẻ ít gặp trong cuộc sống văn phòng. Nếu ta sửa thành sKey = prefixKey & (i Mod 100000), tức hơn 1 triệu key nhưng số key duy nhất là 100 000, và vẫn độ dài ấy thì có lẽ đít thon ít mỡ sẽ cho collection biết thế nào là lễ độ.

Mọi người thử xem sao nhé.
Dạ Bác, nếu chỉ có danh mục mã hàng thôi thì số key duy nhất con làm việc không quá 10 000 , còn nếu liên quan mã và ngày tháng thì số lượng key duy nhất có lẽ cũng không vượt quá 100 000 ạ. Con test thử kết quả như sau Bác, thử chạy mấy lần thì trên máy của con Dic vẫn chậm hơn Col một chút Bác ạ (con đính kèm tập tin Bác xem ạ):
1613794410501.png
Ở chỗ môi trường con làm việc nếu dữ liệu lớn (ví dụ là 1triệu như thế này ) mà thời gian nhanh chậm không quá 30 giây thì là chuyện bình thường thôi ạ.
 

File đính kèm

  • test.xlsm
    23.4 KB · Đọc: 14
Upvote 0
Vâng anh, tôi cũng nghĩ như vậy nên tôi cũng nói là "xem thế nào", nghĩa là so sánh với cùng 1 số lượng key thì tốc độ cũng phải bị thay đổi theo chiều dài key
Thử theo anh bảo thì thấy với tỷ lệ key/ dữ liệu càng ít thì Dict càng nhanh, 50.000 keys thì Collect hít khói, 10.000 keys thì thậm chí không có khói để hít. Thế mới thấy cần phải test trên diện vừa rộng vừa sâu

View attachment 254297
Theo như bảng này của Chú Mỹ thì với con nếu làm việc với dữ liệu thông thường trên Excel thì con thấy cột E là phù hợp nhất chọn Dic để thực hành là tốt nhất vừa nhiều chức năng vừa nhanh.
 
Upvote 0
Web KT

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

Back
Top Bottom