Học Dictionary qua các ví dụ đơn giản!

Liên hệ QC

chuot0106

Thành viên gắn bó
Tham gia
20/1/13
Bài viết
2,567
Được thích
1,670
Thực sự thì mình cũng chưa biết tên topic như vậy có hợp lí không(Nếu chưa hợp lí mong BQT sửa giúp), mình nêu mục đích của topic này luôn.
Bởi vì trên GPE đã có topic về vấn đề này rồi tuy nhiên các topic đó cũng chưa đi sâu lắm về "Dic" bản thân mình rất khó tiếp thu(cá nhân mình thôi). bởi vậy mình xin phép BQT được lập Topic mới này giành cho những người mới chập chững nghiên cứu về "Dic" như mình với mục đích chính như sau:
+ Mong các bạn có kinh nghiệm về "Dic" vào chia sẻ kinh nghiệm của bả n thân về việc học "Dic".
+ Các bạn có kinh nghiệm về "Dic" đưa ra các bài tập từ cơ bản đến đến nâng cao để các thành viên mới thực hành.
+ Các thành viên mới có thể đưa ra các câu hỏi cũng như bài tập liên quan để các thành viên có kinh nghiệm giúp đỡ.

Tất cả các mục đích này dựa trên tinh thần chia sẻ, giao lưu, học hỏi.
Rất mong nhận được sự chia sẻ của các bạn!
 
???
chia sẻ với bạn cách học Dic của mình :
nếu yêu cầu bài toán có yếu tố trùng lặp ,hay duy nhất thì ta nên nghĩ đến dictionary , việc sử dụng dictionary thông thường theo trình tự sau :
+ xác đinh yếu tố duy nhất,hay tạo ra yếu tố duy nhất không trùng lặp
+ Sử dụng công cụ scripting.dictionary ta sẽ biết được : số lượng + vị trí +.... của yếu tố duy nhất hay trùng lặp
+ Dựa vào các kết quả mà Dic cung cấp để xây dựng thuật toán ,hướng giải quyết yêu cầu ban đầu
Rất cảm ơn sự chia sẻ của bạn:
+ Cách xác định yếu tố duy nhất để làm Key thì tôi đã biết. Tuy nhiên cách sử dụng các công cụ(Theo tôi nghĩ là các phương thức, thuộc tính) của scripting.dictionary để xác định vị trí thì tôi biết còn xác định số lượng, ... thì tôi chưa rõ lắm. Nếu có thể bạn có thể giúp tôi hiểu sâu hơn về các công cụ của scripting.dictionary được không? Hoặc có tài liệu nào nói về "Dic" thì cho tôi xin với!
 
Upvote 0
em đoán anh đang đề cập đến advanced filter ,remove duplicate đúng không?
Um mình nói đến cái phương thức RemoveDuplicates. Cách này vẫn còn nguyên công thức.
PHP:
Sub abc()
[A1:F10000].RemoveDuplicates 2, 1
Range([A2], [A65536].End(3)) = [Row(a:A)]
End Sub
 
Upvote 0
Um mình nói đến cái phương thức RemoveDuplicates. Cách này vẫn còn nguyên công thức.
PHP:
Sub abc()
[A1:F10000].RemoveDuplicates 2, 1
Range([A2], [A65536].End(3)) = [Row(a:A)]
End Sub
- Phương thức này hôm nay em mới được biết.
- Anh Hải co thể giải thích rõ hơn chút nữa không a?.
 
Upvote 0
em nghĩ :với trường hợp giữ lại công thức trong excel, việc ghi dữ liệu vào mảng sẽ phức tạp hơn việc dùng công cụ delete range !

Không có gì phức tạp:

Mã:
Sub XoaDong_dungArray()
    Dim Dic As Object, i As Long, j As Long, k As Long, arr()
    arr = Sheet1.Range("A2:F21").FormulaR1C1
    Set Dic = CreateObject("Scripting.Dictionary")
    For i = 1 To UBound(arr, 1)
        If Dic.Item(arr(i, 2)) = "" Then
            k = k + 1
            Dic.Item(arr(i, 2)) = k
            arr(k, 1) = k
            For j = 2 To UBound(arr, 2)
                arr(k, j) = arr(i, j)
            Next
        End If
    Next i
    Sheet1.Range("A2").Resize(k, 6).Formula = arr
    Sheet1.Range("A" & k + 2).Resize(UBound(arr, 1) - k, 6).Clear
    Set Dic = Nothing
End Sub
 
Upvote 0
Um mình nói đến cái phương thức RemoveDuplicates. Cách này vẫn còn nguyên công thức.
PHP:
Sub abc()
[A1:F10000].RemoveDuplicates 2, 1
Range([A2], [A65536].End(3)) = [Row(a:A)]
End Sub
Để dùng được cái này có cần phải thiết lập gì thêm không anh? Sao em chạy đoạn code này nó báo lỗi run time error '438'.
 
Upvote 0
Code cho câu 1.
PHP:
Sub abc()
Dim tam(), i As Long
tam = Range([A2], [B65536].End(3)).Value
With CreateObject("scripting.dictionary")
    For i = 1 To UBound(tam)
        If Not .exists(tam(i, 1)) Then
            .Add tam(i, 1), tam(i, 2)
        End If
    Next
    [F2].Resize(.Count) = Application.Transpose(.keys)
    [G2].Resize(.Count) = Application.Transpose(.items)
End With
End Sub
Và code cho câu 2
PHP:
Sub abc()
Dim tam(), kq(1 To 10000, 1 To 3)
Dim i As Long, k As Long, n As Long, tong As Double
tam = Range([A2], [A65536].End(3)).Resize(, 5).Value
With CreateObject("scripting.dictionary")
    For i = 1 To UBound(tam)
        tong = tam(i, 3) + tam(i, 4) + tam(i, 5)
        If Not .exists(tam(i, 1)) Then
            k = k + 1
            .Add tam(i, 1), k
           kq(k, 1) = tam(i, 1)
           kq(k, 2) = tam(i, 2)
           kq(k, 3) = tong
        Else
            n = .Item(tam(i, 1))
            kq(n, 3) = kq(n, 3) + tong
        End If
    Next
End With
[L2].Resize(k, 3) = kq
End Sub
PS: Mình chỉ viết code thôi, chứ cốc có biết chú thích.
bài này của anh câu 1 em đọc và hiểu được. còn câu 2 hiểu được chắc còn lai dai quá
 
Upvote 0
bài này của anh câu 1 em đọc và hiểu được. còn câu 2 hiểu được chắc còn lai dai quá
Với ai đã biết thì rất dễ, còn nếu chưa biết thì hơi mệt đó. tôi nghiên cứu code này của anh Hải mất 2 ngày liền. Nhưng khi đã hiểu được rồi thấy rất vui và còn có thể áp dụng vào bài tập khác nữa đấy! Bạn cứ thử vooc đi!
 
Upvote 0
Không có gì phức tạp:

Mã:
Sub XoaDong_dungArray()
    Dim Dic As Object, i As Long, j As Long, k As Long, arr()
    arr = Sheet1.Range("A2:F21").FormulaR1C1
    Set Dic = CreateObject("Scripting.Dictionary")
    For i = 1 To UBound(arr, 1)
        If Dic.Item(arr(i, 2)) = "" Then
            k = k + 1
            Dic.Item(arr(i, 2)) = k
            arr(k, 1) = k
            For j = 2 To UBound(arr, 2)
                arr(k, j) = arr(i, j)
            Next
        End If
    Next i
    Sheet1.Range("A2").Resize(k, 6).Formula = arr
    Sheet1.Range("A" & k + 2).Resize(UBound(arr, 1) - k, 6).Clear
    Set Dic = Nothing
End Sub
Anh ThanhLanh có thể giải thích ý nghĩa đoạn code của anh đươc không ạ? Đúng là em không nghĩ bài này dùng mảng được, vậy mà anh...Mong anh chia sẻ!
 
Upvote 0
Um mình nói đến cái phương thức RemoveDuplicates. Cách này vẫn còn nguyên công thức.
PHP:
Sub abc()
[A1:F10000].RemoveDuplicates 2, 1
Range([A2], [A65536].End(3)) = [Row(a:A)]
End Sub
Đã tim hiểu, phương thức này dùng cho excell 2007 thì phải. Mà hình như anh QuangHai đã bị "lạc đề" Topic này đang đề cập đến "Dic" cơ!
 
Upvote 0
Anh ThanhLanh có thể giải thích ý nghĩa đoạn code của anh đươc không ạ? Đúng là em không nghĩ bài này dùng mảng được, vậy mà anh...Mong anh chia sẻ!

Khi đưa Range vào mảng dùng arr = Sheet1.Range("A2:F21").FormulaR1C1 sẽ có công thức. Ngoài ra, bạn đang nghiên cứu về Dic nên ở trên mình giới thiệu một cách dùng Dic khác để bạn tham khảo.
 
Upvote 0
Khi đưa Range vào mảng dùng arr = Sheet1.Range("A2:F21").FormulaR1C1 sẽ có công thức. Ngoài ra, bạn đang nghiên cứu về Dic nên ở trên mình giới thiệu một cách dùng Dic khác để bạn tham khảo.
Anh có thể giải thích giúp em ý nghĩa các câu lệnh trong code của anh không ạ? Em chưa hiểu lắm, vì code anh viết rất khác các code e đã gặp!
 
Upvote 0
Anh có thể giải thích giúp em ý nghĩa các câu lệnh trong code của anh không ạ? Em chưa hiểu lắm, vì code anh viết rất khác các code e đã gặp!


Mã:
Sub XoaDong_dungArray()
    Dim Dic As Object, i As Long, j As Long, k As Long, arr()
    arr = Sheet1.Range("A2:F21").FormulaR1C1 ' Đưa Range vào mảng theo tham chiếu RC (nếu có tham chiếu)
    Set Dic = CreateObject("Scripting.Dictionary")
    For i = 1 To UBound(arr, 1) ' cho i chạy từ dòng đầu đến dòng cuối mảng

        ' Chổ này mới không giống ai nè:
        If Dic.Item(arr(i, 2)) = "" Then ' 
          ' => Nếu khi ta lấy một giá trị của một Key chưa tồn tại trong Dic thì Dic sẽ tự động tạo ra key đó và Item của nó dĩ nhiên còn trống (ở đây là key có tên arr(i, 2), chưa tồn tại)        

            k = k + 1
            Dic.Item(arr(i, 2)) = k ' Gán đại cho Item của Key này một giá trị nào đó
            arr(k, 1) = k   ' Cột đầu là số thứ tự
    
              ' tận dụng mảng đã có, dời tất cả các giá trị của dòng i vảo dòng k bằng vòng lặp sau:
            For j = 2 To UBound(arr, 2)
                arr(k, j) = arr(i, j)
            Next
        End If
    Next i

    Gán các dòng đầu (k dòng) của mảng Arr vào Range (chú ý chỉ lấy K dòng)
    Sheet1.Range("A2").Resize(k, 6).Formula = arr

     nếu có trùng thì  k <> UBound(arr, 1) => dư dòng phải xóa bớt - code ở trên thiếu đk này (các bạn thêm giúp để nếu không có dòng nào trùng sẽ bị lỗi câu lệnh Clear):
    If k <> UBound(arr, 1) then Sheet1.Range("A" & k + 2).Resize(UBound(arr, 1) - k, 6).Clear


    Set Dic = Nothing
End Sub
 
Upvote 0
Mã:
Sub XoaDong_dungArray()
    Dim Dic As Object, i As Long, j As Long, k As Long, arr()
    arr = Sheet1.Range("A2:F21").FormulaR1C1 ' Đưa Range vào mảng theo tham chiếu RC (nếu có tham chiếu)
    Set Dic = CreateObject("Scripting.Dictionary")
    For i = 1 To UBound(arr, 1) ' cho i chạy từ dòng đầu đến dòng cuối mảng

        ' Chổ này mới không giống ai nè:
        If Dic.Item(arr(i, 2)) = "" Then ' 
          ' => Nếu khi ta lấy một giá trị của một Key chưa tồn tại trong Dic thì Dic sẽ tự động tạo ra key đó và Item của nó dĩ nhiên còn trống (ở đây là key có tên arr(i, 2), chưa tồn tại)        

            k = k + 1
            Dic.Item(arr(i, 2)) = k ' Gán đại cho Item của Key này một giá trị nào đó
            arr(k, 1) = k   ' Cột đầu là số thứ tự
    
              ' tận dụng mảng đã có, dời tất cả các giá trị của dòng i vảo dòng k bằng vòng lặp sau:
            For j = 2 To UBound(arr, 2)
                arr(k, j) = arr(i, j)
            Next
        End If
    Next i

    Gán các dòng đầu (k dòng) của mảng Arr vào Range (chú ý chỉ lấy K dòng)
    Sheet1.Range("A2").Resize(k, 6).Formula = arr

     nếu có trùng thì  k <> UBound(arr, 1) => dư dòng phải xóa bớt - code ở trên thiếu đk này (các bạn thêm giúp để nếu không có dòng nào trùng sẽ bị lỗi câu lệnh Clear):
    If k <> UBound(arr, 1) then Sheet1.Range("A" & k + 2).Resize(UBound(arr, 1) - k, 6).Clear


    Set Dic = Nothing
End Sub
Cảm ơn anh nhiều lắm! Anh chú thích rất chi tiết, qua code em học được thêm 2 điều mới, đó là nếu muốn có tham chiếu thì thêm FomulaR1C1 vào. Thứ 2 học được 1 cách dùng khác về "Dic".
 
Upvote 0
Chỉ xóa các dòng trùng trong bảng dữ liệu (không ảnh hưởng đến các cột ngoài vùng dữ liệu) và nếu dữ liệu không có ô nào rỗng (blank) thì có thể dùng code này:
Sub XoaDong()
Dim Rng As Range, i As Long, Dic As Object, k As Long
Set Rng = Sheet1.Range("A2:F21")
Set Dic = CreateObject("Scripting.Dictionary")
Application.ScreenUpdating = False
For i = 1 To Rng.Rows.Count
If Not Dic.Exists(Rng(i, 2).Value) Then
k = k + 1
Dic.Add Rng(i, 2).Value, k
Rng(i, 1) = k
Else
Rng(i, 1).Resize(, 6) = Empty
End If
Next i
If k < Rng.Rows.Count Then
Rng.SpecialCells(4).Delete Shift:=xlUp
End If
Set Dic = Nothing
Application.ScreenUpdating = True
End Sub
Còn nếu xóa nguyên dòng thì thì chạy vòng lặp từng Cells cột B và EntireRow.Delete.
Anh leonguyenz có thể giải thích giúp em ý nghĩa của dòng này được không ạ? Các dòng còn lại em đã hiểu rồi!
Rng.SpecialCells(4).Delete Shift:=xlUp
 
Lần chỉnh sửa cuối:
Upvote 0
Câu hỏi số 5: (Câu hỏi của thầy SiwTom đưa)

Đề bài đã viết rõ trong File.
 

File đính kèm

  • Cauhoi5_Dic.rar
    2.8 KB · Đọc: 51
Upvote 0
Thử xóa vầy xem sao
PHP:
Sub XoaXoaXoa()
    Dim i As Long, j As Long, k As Long, arr()
    arr = Range([A2], [F65536].End(3)).Formula
    With CreateObject("Scripting.Dictionary")
        For i = 1 To UBound(arr, 1)
            If Not .exists(arr(i, 2)) Then
                k = k + 1
                .Add (arr(i, 2)), ""
                arr(k, 1) = k
            Else
                For j = 1 To UBound(arr, 2)
                    arr(i, j) = ""
                Next
            End If
        Next i
    End With
    [A2].Resize(i - 1, 6) = arr
     Range("A2:F" & i).SpecialCells(4).Delete xlShiftUp
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Câu hỏi số 5: (Câu hỏi của thầy SiwTom đưa)

Đề bài đã viết rõ trong File.
Đổi gió tý, mình Google được tý SQL, dùng thử xem sao, các bạn sửa giúp nhé xem còn lỗi hay dài quá không? Tạo folder C:\SQL, giải nén 2 file vào đó. Sheet1 là đề bài, mình copy đề sang sheet2 và chỉnh sửa bảng dữ liệu một chút; đặt name data là bảng dữ liệu, name nguoi_loc là tên người cần lọc. Kết quả ở cột D sheet2. Mỗi lần sửa dữ liệu (nhưng không thay đổi số hàng) thì bấm chuột phải vào 1 ô ở kết quả, chọn Refresh data. Nếu thay đổi cả số hàng trong bảng dữ liệu thì phải sửa lại name rồi Refresh. Bấm chuột phải vào ô kết quả, chọn Edit querry để sửa lệnh. Câu lệnh mình dùng là
SELECT DISTINCT data.TP FROM `C:\SQL\Cauhoi5_Dic`.data data WHERE data.TP NOT IN (SELECT data.TP FROM `C:\SQL\Cauhoi5_Dic`.data data INNER JOIN `C:\SQL\Cauhoi5_Dic`.nguoi_loc nguoi_loc ON data.Ten LIKE nguoi_loc.Nguoi & '%')
 

File đính kèm

  • Cau5.rar
    4.3 KB · Đọc: 20
Lần chỉnh sửa cuối:
Upvote 0
Đổi gió tý, mình Google được tý SQL, dùng thử xem sao, các bạn sửa giúp nhé xem còn lỗi hay dài quá không? Tạo folder C:\SQL, giải nén 2 file vào đó. Sheet1 là đề bài, mình copy đề sang sheet2 và chỉnh sửa bảng dữ liệu một chút; đặt name data là bảng dữ liệu, name nguoi_loc là tên người cần lọc. Kết quả ở cột D sheet2. Mỗi lần sửa dữ liệu (nhưng không thay đổi số hàng) thì bấm chuột phải vào 1 ô ở kết quả, chọn Refresh data. Nếu thay đổi cả số hàng trong bảng dữ liệu thì phải sửa lại name rồi Refresh. Bấm chuột phải vào ô kết quả, chọn Edit querry để sửa lệnh. Câu lệnh mình dùng là
SELECT DISTINCT data.TP FROM `C:\SQL\Cauhoi5_Dic`.data data WHERE data.TP NOT IN (SELECT data.TP FROM `C:\SQL\Cauhoi5_Dic`.data data INNER JOIN `C:\SQL\Cauhoi5_Dic`.nguoi_loc nguoi_loc ON data.Ten LIKE nguoi_loc.Nguoi & '%')
Thực ra tất cả những bài toán ví dụ đưa ra ơ đây có nhiều công cụ để giải quyết tuy nhiên chúng ta bám sát chủ đề đó là dùng "Dic", dù sao cũng cảm ơn bạn!
 
Upvote 0
Nếu hết ngày hôm nay mà không nhận được đáp án câu hỏi 5 ở bài #75thì em mong thầy Siwtom công bố đáp án ạ! Em cũng chưa làm ra do kiến thức về "Dic" cũng chưa nắm hết ạ!
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu hết ngày hôm nay mà không nhận được đáp án câu hỏi 5 ở bài #75thì em mong thầy Siwtom công bố đáp án ạ! Em cũng chưa làm ra do kiến thức về "Dic" cũng chưa nắm hết ạ!

Thực ra bạn chỉ bí về thuật toán còn các thuộc tính và phương thức của dic bạn nắm gọn trong lòng bàn tay rồi còn gì.
Chính vì thế tôi mới nhấn mạnh: thuật toán là cái khó và phải học mãi. Rèn luyện tư duy.

Có thể có nhiều hướng, tôi nghĩ đơn giản thế này. Ta duyệt cột A và cho vào dic những tên thành phố. Kết quả phải đạt được là: những tên trong dic mà C1 đã đến thì có Item = 1, những tên chưa đến thì có Item = 0. Sau khi duyệt hết cột A (có thể A, B đập vào mảng trước đó) thì đọc ra những Key mà có Item = 0. Thế thôi.
Tôi không chỉ rõ cách thêm Key vào dic như thế nào vì nếu chỉ ra thì xong bài toán rồi còn gì.
 
Upvote 0
Web KT
Back
Top Bottom