Tìm kiếm với dữ liệu gần đúng
Sử dụng DIC
Tôi cũng chỉ nghe láng máng SQL nên chưa biết j. Với dữ liệu hơn 40 triệu dòng khả dùng DIC cũng chạy được
E có học mót sử dụng DIC, tuy nhiên theo yêu cầu của bài toán, Nếu như loại số máy bên Bang A giống hệt như loại số máy bên Bang B thì e làm được. Nhưng loại số máy bên bảng A có bổ sung thêm các ký tự đằng sau nên chưa biết sử lý tình huống thế nào
Nhân tiện bài toán của chủ Topic, E pốt file hỏi các thành viên
Mong nhận được sự trợ giúpSub LoaiXe() Application.ScreenUpdating = False Dim T As Double, Dic1 As Object Dim MyRng As Range Dim SoMay, SoKhung, MoDel, HangXe Dim Source, ThongTin, Itm Dim I As Long T = Timer With Sheet1 SoMay = .Range(.[E2], .[E1048576].End(3)).Value End With With Sheet2 Set MyRng = Range(.Range("A2"), .Range("A1048576").End(xlUp)) Source = MyRng MoDel = MyRng.Offset(, 1) HangXe = MyRng.Offset(, 2) End With ReDim ThongTin(1 To UBound(SoMay), 1 To 2) Set Dic1 = CreateObject("Scripting.Dictionary") For I = 1 To UBound(Source) Itm = CStr(Source(I, 1)) If Itm > "" And Not Dic1.exists(Itm) Then Dic1.Add Itm, I End If Next For I = 1 To UBound(SoMay) Itm = CStr(SoMay(I, 1)) If Dic1.exists(Itm) Then ThongTin(I, 1) = MoDel(Dic1.Item(Itm), 1) ThongTin(I, 2) = HangXe(Dic1.Item(Itm), 1) End If Next Sheet1.Range("G2").Resize(UBound(SoMay), 2) = ThongTin MsgBox Timer - T, , "Thoi gian" Application.ScreenUpdating = True End SubMong các thành viên giúp đỡ
40 triệu dòng lớn hơn giới hạn của excel thì dic không chạy nổi.
Nếu số dòng ít hơn, theo mình thấy bảng B các số máy là duy nhất, số máy bảng A mới lặp lại nên gán số máy ở bảng B vào dictionary có vẻ chưa hợp lý. Mình chỉ nghĩ ra cách dùng 2 vòng lặp lồng nhau: vòng for duyệt qua số máy bảng A và vòng Do Loop duyệt qua số máy bảng B để so sánh 2 số máy.
Giả sử dữ liệu trong giới hạn của excel..mong các thành viên hỗ trợ
Bên bảng B chỉ là vài ký tự đầu của bên bảng A. Đâu có dùng Dictionary được. Có cách dùng ArrayCollection, nhưng rất rắc rối.
Cách dễ hơn hêt là sort bảng B (1), rồi dùng phép tìm nhị phân – binary sort (2).
(1) Bạn Siwtom có bài nói về các cách sort. Chịu khó tìm sẽ được.
(2) Cách tìm nhị phân rất căn bản. Bạn tự làm được mà.
dạ. e nghĩ có thể thêm ký tự đại diện * để thay thế cho các ký tự đằng sau như dùng hàm ngoài bảng tính
Trong khi chờ đợi giải pháp sao không thử code này
Sub FindText()
Dim BangB(), I, Found, FoundFirst
With Sheet2
BangB = .Range(., ..End(3)).Value
End With
For I = 1 To UBound(BangB)
Set Found = Sheet1..Find(BangB(I, 1), , , 2)
If Not Found Is Nothing Then
FoundFirst = Found.Address
Do
Set Found = Sheet1..FindNext(Found)
Found.Offset(, 2) = BangB(I, 2)
Found.Offset(, 3) = BangB(I, 3)
Loop Until Found.Address = FoundFirst
End If
Next
End Sub
Nếu dữ liệu nhiều mà dùng code bài số 7 chắc phải đi pha cafe uống quá
Thử thêm với code này
Sub FindText()
Dim BangA(), BangB(), I, J, Found, FoundFirst
With Sheet1
BangA = .Range(., ..End(3)).Resize(, 8).Value
End With
With Sheet2
BangB = .Range(., ..End(3)).Value
End With
For I = 1 To UBound(BangA)
For J = 1 To UBound(BangB)
If BangA(I, 5) Like BangB(J, 1) & "*" Then
BangA(I, 7) = BangB(J, 2)
BangA(I, 8) = BangB(J, 3)
End If
Next
Next
Sheet1..Resize(I – 1, 8) = BangA
End Sub
cả 2 cách của a QuangHai đều chạy tốt.cách 2 cho kết quả nhanh hơn nhiều ạh
e cảm ơn a. cơ mà cho e hỏi thêm có thể vận dụng dic cho bài toán này ko a? vì dữ liệu tương đối lớn
Chắc là không thể dùng Dic được đâu, bài này Dic không phù hợp.
Nếu bạn muốn thử với Dic thì bạn tham khảo Code sau:
Sub LoaiXe() Dim BangA(), BangB() Dim Dic As Object Dim i As Long, L As Long, k As Long, Tmp As String With Sheet1 BangA = .Range(.[a2], .[A1000000].End(3)).Resize(, 8).Value End With With Sheet2 BangB = .Range(.[a2], .[C1000000].End(3)).Value End With Set Dic = CreateObject("Scripting.Dictionary") With Dic For i = 1 To UBound(BangB, 1) If Not .Exists(BangB(i, 1)) Then k = k + 1 .Add BangB(i, 1), k End If Next For i = 1 To UBound(BangA, 1) For L = 1 To Len(BangA(i, 5)) Tmp = Left(BangA(i, 5), L) If .Exists(Tmp) Then BangA(i, 7) = BangB(.Item(Tmp), 2) BangA(i, 8) = BangB(.Item(Tmp), 3) Exit For End If Next Next End With Sheet1.[a2].Resize(i - 1, 8) = BangA End Sub
Không có dữ liệu lớn để thử nhưng cảm giác vẫn cho thấy là nếu dùng Dic sẽ cho tốc độ chậm hơn 2 mảng lồng, thêm nữa thấy nó rắc rối quá
Chiẻ là tham khảo thôi mà anh. Nhưng mà em nghĩ tốc độ cũng không đến nỗi nào bởi nó chỉ duyệt qua số phần tử trong 1 chuỗi rồi đối chiếu với Dic nếu thỏa thì thoát ngay.
2 mảng lồng mà cũng dùng Exit For thì tốc độ sẽ nhanh hơn nhiều anh nhỉ?
Sao dám Exit for, nếu sort bảng A trước thì mới có thể dùng Exit for
Vâng, ấy là đoán vậy thôi anh chứ dữ liệu thất mình có biết mặt mũi nó như thế nào đâu. Cứ để chủ Topic thử sai thì lại hỏi –=0.
Vòng lặp bảng B nằm trong vòng lặp bảng A. Vòng lặp B có thể dùng exit for hoặc do loop.
Cái này chưa chắc bởi nếu mã xe giống nhau phần đầu mà sai phần sau thì toi.
Ví dụ:
LC3C – Airblade – Honda
LC3C1 – Lead – Honda
Nếu mã xe có dạng như ví dụ thì có thể sort bảng B theo thứ tự giảm dần rồi dùng vòng lặp. Khi đó mã LC3C1 sẽ xuất hiện trước LC3C, có thể exit for ở LC3C1.
Chuẩn rồi ạ, đó là hướng code áp dụng bài #11 + nhận xét #13 + đề cập tại #14
Dạ.. topic này e mượn tình huống từ 1 topic khác đã nêu ở #1 để làm bài học cho mình. Thực tế chưa gặp trường hợp này bao giờ và cũng ko biết dữ liệu thật mặt mũi thế nào ạh, hì
E cảm ơn mng nhiều
Tôi đã đoán là bạn muốn học cho nên tôi mới bảo bạn chịu khó đi tìm 2 trong những thuật toán căn bản của lập trình: sort và tìm nhị phân.
www.giaiphapexcel.com/diendan/threads/t%C3%ACm-ki%E1%BA%BFm-v%E1%BB%9Bi-d%E1%BB%AF-li%E1%BB%87u-g%E1%BA%A7n-%C4%91%C3%BAng.94910/
Xây dựng Lương 3P, KPI cho Doanh nghiệp
Làm thế nào để trả lương cho nhân viên chính xác nhất? Đây là một trong những câu hỏi khó trong quản trị nhân...
Xem khóa học