Tìm ký tự giống nhau trong các cells

Liên hệ QC

pat_ftu

Thành viên mới
Tham gia
16/1/07
Bài viết
19
Được thích
2
Em gặp tình huống sau, mong các cao thủ chỉ giáo ạ!

A
1​
Bảo hiểm xã hội Việt Nam
2​
BHXH Việt Nam
3​
Bảo hiểm xh Việt Nam
4​
BH xã hội Việt Nam

Em muốn tìm ký tự giống nhau giữa các ô A1: A4, cần dùng hàm gì ạ?
 
Theo mình Bạn cần nêu rõ khái niệm ký tự trong cách bạn hiểu ở bài này bạn nhé.
 
Thế nào là "cụm từ"? Phải đúng là "Việt Nam", hay chỉ "Việt" và "Nam"
"Bảo Hiểm Xã Hội" là một cụm từ, hay "Bảo Hiểm" là một cụm và "Xã Hội" là một cụm nữa?
 
Thế nào là "cụm từ"? Phải đúng là "Việt Nam", hay chỉ "Việt" và "Nam"
"Bảo Hiểm Xã Hội" là một cụm từ, hay "Bảo Hiểm" là một cụm và "Xã Hội" là một cụm nữa?
Ý mình nếu coi 4 cells mỗi cells gồm tập hợp các ký tự, giao của 4 tập hợp này sẽ là "Việt Nam"
 
Ý mình nếu coi 4 cells mỗi cells gồm tập hợp các ký tự, giao của 4 tập hợp này sẽ là "Việt Nam"
Ý bạn chả rõ gì cả.
Nếu 4 cells có:
BHX Hội Việt Nam
BH Xã Hội Việt Nam
Xã Hội Việt Nam Bảo Hiểm
Bảo Hiểm Xã Hội Việt Nam
Thì theo lô gic toán, giao là "Hội Việt Nam". Có phải vậy không?
 
Ý bạn chả rõ gì cả.
Nếu 4 cells có:
BHX Hội Việt Nam
BH Xã Hội Việt Nam
Xã Hội Việt Nam Bảo Hiểm
Bảo Hiểm Xã Hội Việt Nam
Thì theo lô gic toán, giao là "Hội Việt Nam". Có phải vậy không?
Ở Việt Nam lập hội không xin phép là vi phạm pháp luật, tội khá nghiêm trọng
 
Bài toán tìm cụm từ chung hơi khó. Hỏi ở đây có lẽ là sai diễn đàn.
Dân chuyên về cụm từ là dân SEO (Search Engine Optimizer)

Nếu giải theo cách vét cạn thì đại khái là:
Đầu tiên hết tách từng từ của cell1 ra.
Mỗi từ:
. tìm xem nó có trong các cells còn lại.
. chỉ cần không có trong 1 cell khác thì dừng lại, qua từ kế
. nếu có trong tất cả các cells thì:
. . nhập nó vào từ kế tiếp của cell1 thành 1 cụm và lại tiếp tục tìm cụm này trong các cells còn lại
 
Cảm ơn các huynh đệ nhiều!
 
Thuật toán áp dụng:
  1. Chọn chuỗi có ít "từ" nhất (Chuỗi A)
  2. Tách chuỗi A ra thành từng từ
  3. Lọc ra các từ có ở tất cả các chuỗi (Tập hợp B)
  4. Liệt kê tất cả các từ/ cụm từ được tạo từ các từ ở tập hợp B có trong chuỗi A (Tập hợp C)
  5. Kiểm tra từng từ/ cụm từ trong tập hợp C (theo thứ tự số lượng từ nhiều đến ít) xem có xuất hiện trong tất cả các chuỗi không.
  6. Dừng lại và trả về kết quả khi tìm thấy từ/ cụm từ xuất hiện trong tất cả các chuỗi.
Mã:
Option Compare Text
Function IntersectWords(ByVal aText As Variant) As String
Dim i As Long, j As Long, k As Long, lLength As Long, lMinLength As Long, sMainText As String, aMainWords As Variant, sTmp As String, oReg As Object
aText = aText
sMainText = aText(1, 1)
lMinLength = CountWords(aText(1, 1))
For i = 1 To UBound(aText, 1)
    aText(i, 1) = Application.Trim(aText(i, 1))
    lLength = CountWords(aText(i, 1))
    If lLength < lMinLength Then
        sMainText = aText(i, 1)
        lMinLength = lLength
    End If
Next
If lMinLength = 0 Then Exit Function
aMainWords = Split(sMainText, " ")
For j = LBound(aMainWords, 1) To UBound(aMainWords, 1)
    For i = 1 To UBound(aText, 1)
        If Not CheckInStr(aText(i, 1), aMainWords(j)) Then
            aMainWords(j) = ""
            Exit For
        End If
    Next
Next
k = UBound(aMainWords, 1)
For i = LBound(aMainWords, 1) To k
    If aMainWords(i) <> "" Then
        sTmp = aMainWords(i)
        For j = i + 1 To k
            If aMainWords(j) <> "" Then
                sTmp = sTmp & vbBack & aMainWords(j)
                ReDim Preserve aMainWords(LBound(aMainWords, 1) To UBound(aMainWords, 1) + 1)
                aMainWords(UBound(aMainWords, 1)) = sTmp
            Else
                Exit For
            End If
        Next
    End If
Next
sMainText = Application.Trim(Join(aMainWords, " "))
sMainText = Replace(Replace(sMainText, " ", vbTab), vbBack, " ")
aMainWords = Split(sMainText, vbTab)
SortLengthZA aMainWords
For j = LBound(aMainWords, 1) To UBound(aMainWords, 1)
    For i = 1 To UBound(aText, 1)
        If Not CheckInStr(aText(i, 1), aMainWords(j)) Then GoTo NotFound
    Next
    IntersectWords = aMainWords(j)
    Exit Function
NotFound:
Next
End Function
Private Function CountWords(ByVal sStr As String) As Long
If sStr <> "" Then CountWords = Len(sStr) - Len(Replace(sStr, " ", "")) + 1
End Function
Private Function CheckInStr(ByVal sStr As String, ByVal sChildStr As String) As Boolean
CheckInStr = InStr(" " & sStr & " ", " " & sChildStr & " ")
End Function
Private Sub SortLengthZA(ByRef Arr As Variant)
Dim i As Long, j As Long, sTmp As String
For i = LBound(Arr, 1) To UBound(Arr, 1) - 1
    For j = i + 1 To UBound(Arr, 1)
        If CountWords(Arr(j)) > CountWords(Arr(i)) Then
            sTmp = Arr(i): Arr(i) = Arr(j): Arr(j) = sTmp
        End If
    Next
Next
End Sub
 

File đính kèm

  • GPE.xlsm
    26.8 KB · Đọc: 12
@pat_ftu Góp thêm 1 cách tham khảo
Số liệu bắt đầu từ A1 sheet1
Mã:
Sub TimNhomTu()
Dim Nguon
Dim Mang
Dim Chuoi
Dim Kq
Dim rws
Dim i, j, k, x, y, z, t
Nguon = Sheet1.Range("A1").CurrentRegion
rws = UBound(Nguon)
For i = 1 To rws
    Nguon(i, 1) = Application.Trim(Nguon(i, 1))
    If k < Len(Nguon(i, 1)) Then
        t = i
        k = Len(Nguon(i, 1))
    End If
Next i
Mang = Split(Nguon(t, 1))
k = UBound(Mang)
With CreateObject("Scripting.Dictionary")
    For j = 0 To k
        For y = 0 To k - j
            Chuoi = ""
            For z = y To y + j
                Chuoi = Chuoi & " " & Mang(z)
            Next z
            .Item(.Count) = Trim(Chuoi)
        Next y
    Next j
    ReDim Kq(1 To .Count, 1 To 2)
    k = 0
    For i = 0 To .Count - 1
        t = .Items()(i)
        Kq(i + 1, 1) = t
        For x = 1 To rws
            If InStr(1, Nguon(x, 1), t, 1) Then Kq(i + 1, 2) = Kq(i + 1, 2) + 1
        Next x
        If k < Kq(i + 1, 2) Then k = Kq(i + 1, 2)
    Next i
End With
If k < rws Then MsgBox "Khong co cum tu chung": Exit Sub
With Sheet1
    .Columns(3).Clear
    x = 0
    For i = UBound(Kq) To 1 Step -1
        If Kq(i, 2) = k Then
            x = x + 1
            .Range("C" & x) = Kq(i, 1)
            .Range("D" & x) = Kq(i, 2)
        Else
            If .Range("C1") <> "" Then Exit For
        End If
    Next i
    .UsedRange.Columns.AutoFit
End With
End Sub
 
Với dữ liệu

Giới ăn chơi Hà Thành
Thanh niên Hà Thành ăn chơi trác táng
Thanh niên Hà Thành không ăn chơi bằng thanh niên Sài Thành
Thanh niên Hà Thành nói không với ăn chơi


thì code của huuthang_bd và CHAOQUAY trả vể "ăn chơi". Tại sao không là "Hà Thành"? Thậm chí "Hà Thành" dài hơn. Đếm ký tự bằng mắt hay bằng LEN đều dài hơn.
 
Với dữ liệu

Giới ăn chơi Hà Thành
Thanh niên Hà Thành ăn chơi trác táng
Thanh niên Hà Thành không ăn chơi bằng thanh niên Sài Thành
Thanh niên Hà Thành nói không với ăn chơi


thì code của huuthang_bd và CHAOQUAY trả vể "ăn chơi". Tại sao không là "Hà Thành"? Thậm chí "Hà Thành" dài hơn. Đếm ký tự bằng mắt hay bằng LEN đều dài hơn.
Cái này phải chờ xem ý chủ thớt thế nào đã anh. Ưu tiên từ/ cụm từ xuất hiện trước hay có số lượng ký tự nhiều hơn hay thế nào đó thì mình tính tiếp.
Theo như mô tả thuật toán trong code của em thì chỉ lấy từ/ cụm từ có số lượng từ nhiều nhất tìm thấy đầu tiên, chưa xét đến các điều kiện khác.
 
Theo như mô tả thuật toán trong code của em thì chỉ lấy từ/ cụm từ có số lượng từ nhiều nhất tìm thấy đầu tiên, chưa xét đến các điều kiện khác.
Nếu thế thì với dữ liệu

Giới ăn chơi Hà Thành - bắc Việt Nam
Thanh niên Hà Thành ăn chơi trác táng
Thanh niên Hà Thành không ăn chơi bằng thanh niên Sài Thành
Thanh niên Hà Thành nói không với ăn chơi


kết quả cũng phải là "ăn chơi". Nhưng code trả về "Hà Thành".

Nếu chỉ là Giới ăn chơi Hà Thành - Việt Nam thì lại trả về "ăn chơi".
---
Nguyên nhân là do code lấy chuỗi ngắn nhất trong các chuỗi C4, C5, ... làm "điểm xuất phát"? Nếu có nhiều chuỗi cùng ngắn nhất thì lấy chuỗi cuối cùng?

Trường hợp Giới ăn chơi Hà Thành và Giới ăn chơi Hà Thành - Việt Nam thì lấy chuỗi C4 (ngắn nhất) làm "điểm xuất phát", còn với Giới ăn chơi Hà Thành - bắc Việt Nam thì lấy C5 (C4 và C5 cùng độ dài LEN) làm "điểm xuất phát"?
 
Lần chỉnh sửa cuối:
Nếu thế thì với dữ liệu

Giới ăn chơi Hà Thành - bắc Việt Nam
Thanh niên Hà Thành ăn chơi trác táng
Thanh niên Hà Thành không ăn chơi bằng thanh niên Sài Thành
Thanh niên Hà Thành nói không với ăn chơi


kết quả cũng phải là "ăn chơi". Nhưng code trả về "Hà Thành".

Nếu chỉ là Giới ăn chơi Hà Thành - Việt Nam thì lại trả về "ăn chơi".
---
Nguyên nhân là do code lấy chuỗi ngắn nhất trong các chuỗi C4, C5, ... làm "điểm xuất phát"? Nếu có nhiều chuỗi cùng ngắn nhất thì lấy chuỗi cuối cùng?

Trường hợp Giới ăn chơi Hà Thành và Giới ăn chơi Hà Thành - Việt Nam thì lấy chuỗi C4 (ngắn nhất) làm "điểm xuất phát", còn với Giới ăn chơi Hà Thành - bắc Việt Nam thì lấy C5 (C4 và C5 cùng độ dài LEN) làm "điểm xuất phát"?
Chắc anh hiểu nhầm ý em. Code của em tìm thấy đầu tiên không phải là xuất hiện trước trong chuỗi do thứ tự bị thay đổi khi sử dụng thuật toán bubble sort.
Nếu ưu tiên vị trí xuất hiện thì sẽ phức tạp hơn nhiều do phải xét vị trí tương đối của từng từ/ cụm từ với nhau theo từng đôi một ở tất cả các chuỗi và từ đó xác định từ/ cụm từ được ưu tiên (có thể có trường hợp không xác định được)
 
Thấy đông vui, cũng ráng góp code liệt kê tất cả cụm từ trùng, dùng tạm vì kết quả hơi kỳ kỳ
Mã:
Option Compare Text

Sub TuTrung()
  Dim sArr(), tmp(), S, iStr$, Res$
  Dim sRow&, K&, i&, j&, n&, c&
  sArr = Range("B3:B6").Value
  sRow = UBound(sArr)
  S = Split(Application.Trim(sArr(1, 1)), " ")
  K = UBound(S)
  ReDim tmp(1 To 2, 0 To K)
  For j = 0 To K
    tmp(1, j) = S(j): tmp(2, j) = K - j
  Next j
  For i = 2 To sRow
    S = Split(Application.Trim(sArr(i, 1)), " ")
    For j = 0 To K
      If Len(tmp(1, j)) > 0 Then
        iStr = tmp(1, j)
        For n = 0 To UBound(S)
          If iStr = S(n) Then Exit For
        Next n
        If n = UBound(S) + 1 Then
          tmp(1, j) = Empty
        ElseIf tmp(2, j) > 0 Then
          For c = 1 To tmp(2, j)
            If n + c <= UBound(S) Then
              If tmp(1, j + c) <> S(n + c) Then
                tmp(2, j) = c - 1: Exit For
              End If
            Else
              tmp(2, j) = c - 1: Exit For
            End If
          Next c
        End If
      End If
    Next j
  Next i
  For j = 0 To K
    If Len(tmp(1, j)) > 0 Then
      If Len(Res) = 0 Then Res = tmp(1, j) Else Res = Res & "; " & tmp(1, j)
      For c = 1 To tmp(2, j)
        Res = Res & " " & tmp(1, j + c)
      Next c
      j = j + tmp(2, j)
    End If
  Next j
  [B1] = Res
End Sub
 

File đính kèm

  • Sap xe du lieu.xlsb
    15.9 KB · Đọc: 10
Nếu thế thì với dữ liệu

Giới ăn chơi Hà Thành - bắc Việt Nam
Thanh niên Hà Thành ăn chơi trác táng
Thanh niên Hà Thành không ăn chơi bằng thanh niên Sài Thành
Thanh niên Hà Thành nói không với ăn chơi


kết quả cũng phải là "ăn chơi". Nhưng code trả về "Hà Thành".

Nếu chỉ là Giới ăn chơi Hà Thành - Việt Nam thì lại trả về "ăn chơi".
---
Nguyên nhân là do code lấy chuỗi ngắn nhất trong các chuỗi C4, C5, ... làm "điểm xuất phát"? Nếu có nhiều chuỗi cùng ngắn nhất thì lấy chuỗi cuối cùng?

Trường hợp Giới ăn chơi Hà Thành và Giới ăn chơi Hà Thành - Việt Nam thì lấy chuỗi C4 (ngắn nhất) làm "điểm xuất phát", còn với Giới ăn chơi Hà Thành - bắc Việt Nam thì lấy C5 (C4 và C5 cùng độ dài LEN) làm "điểm xuất phát"?
Có lẽ không phải do chuỗi ngắn nhất vì nếu chuỗi ngắn nhất không đạt yêu cầu thì coi như cả mảng dữ liệu đều không đạt.
Chắc lỗi là do lúc xuất kết quả, không biết ý đầu bài là xuất hết hay là 1 kết quả rồi thôi nên mới bị vậy bác.
 
Có lẽ không phải do chuỗi ngắn nhất vì nếu chuỗi ngắn nhất không đạt yêu cầu thì coi như cả mảng dữ liệu đều không đạt.
Chắc lỗi là do lúc xuất kết quả, không biết ý đầu bài là xuất hết hay là 1 kết quả rồi thôi nên mới bị vậy bác.
À đấy là đoán mò thôi chứ tôi ngại dò code quá.
 
Web KT
Back
Top Bottom