Xóa chuỗi trùng

Liên hệ QC

anhphuquocvn

Thành viên mới
Tham gia
3/3/18
Bài viết
8
Được thích
0
Giới tính
Nam
Kính nhờ Anh Chi Em giúp đỡ:
làm sao viết code chuyển chuỗi TinA1. TinA2. TinA3. LyA1. LyA2. LyA3. HoaA1. HoaA2. -> TinA1.A2.A3. LyA1.A2.A3. HoaA1.A2
Xin chân thành cám ơn!
 
Mã:
Function SaiRangChiu(s As String) As String
' get rid of repeating and redundant subject names
' That is: TinA1. TinA2. TinA3. LyA1. LyA2. LyA3. HoaA1. HoaA2. -> TinA1.A2.A3. LyA1.A2.A3. HoaA1.A2
' within the following code: Toan, Tin,... are called subject categories, and A1, A2 are subject subdivisions
Dim aSubjectCats ' serves as an array of subject categories
Dim aSubjects() As String ' this array is for packing subjects into their respective cats
Dim sPart ' represents each subject element within input string
Dim aLo As Integer, aHi As Integer, cat As Integer ' counters
aSubjectCats = Array("Toan", "Tin", "Ly", "Hoa", "Van") ' define subject categories
aLo = LBound(aSubjectCats)
aHi = UBound(aSubjectCats)
ReDim aSubjects(aLo To aHi)
For Each sPart In Split(Replace(s, " ", ""), ".") ' traverse input string in parts
  For cat = aLo To aHi
    If sPart Like aSubjectCats(cat) & "*" Then Exit For ' search subject's category
  Next cat
  If cat <= aHi Then ' category found
    If aSubjects(cat) <> "" Then ' category already registered
      aSubjects(cat) = aSubjects(cat) & "." & Replace(sPart, aSubjectCats(cat), "")
    Else
      aSubjects(cat) = sPart ' place subject in, and at the same time, register cat
    End If
  End If
Next sPart
SaiRangChiu = Replace(Application.Trim(Join(aSubjects, " ")), " ", ". ")
End Function

Chú thích:
Muốn thêm bớt môn nào thì chỉnh dòng này:
aSubjectCats = Array("Toan", "Tin", "Ly", "Hoa", "Van")
ví dụ
aSubjectCats = Array("Toan", "Tin", "Ly", "Hoa", "Van", "Su") ---> thêm môn sử
 
Lần chỉnh sửa cuối:
Upvote 0
Xin chân thành cảm ơn Bác VetMini đã giúp đỡ!
Trong khi chờ đợi tôi đã xử lý được rồi, như sau:)
'Xoa chuoi trung vd: "TinA1.TinA2.TinA3"->TinA1.A2.A3 (ở đây xử lý 1 môn, nhiều môn thì thêm vòng lặp)
Sub XoaTrung()
Dim M1, M2, x, s As String 'M1:Chua MOn;M2:Chua lop
tenmon = "Tin": s = "TinA1.TinA2.TinA3"
'Chia ra tung chuoi nho khi co dau cham
For Each x In Split(s, ".")
If tenmon = Left(x, Len(tenmon)) Then
M1 = tenmon
M2 = M2 & Mid(x, Len(tenmon) + 1, Len(x) - Len(tenmon)) & "."
End If
Next
s = M1 & M2
MsgBox s
End Sub
 
Upvote 0
Cái nào thấy chạy ra đúng kết quả thì cứ dùng. Không cần phải màu mè hoa lá cành.
Điểm quan trọng nhất là nhận ra giới hạn khi có dữ liệu nằm ngoài dự tính. Thường thì người vết code kinh nghiệm đoán trước được hơn 90% bất trắc về dữ liệu và code sẽ tránh được những điểm sai này. Người không kinh nghiệm chỉ đoán được 0-30% trường hợp.
Kinh nghiệm test giới hạn dữ liệu trong nghề lập trình được gọi là "boundary test". Nó là phần căn bản nhất trong lập trình. Người học lập trình từ căn bản thì đạt trong vòng sơ khởi. Người học lập trình theo kiểu mày mò hoặc đốt giai đoạn thì khá lâu mới đạt được.
 
Upvote 0
anhphuquocvn
Bác có thể sử dụng Biểu thức chính quy


--------------------------
Mã:
Function UniqueSubject(ByVal Text$)
  With VBA.CreateObject("VBScript.RegExp")
    .Global = True: .ignorecase = False
    .Pattern = "([a-z]+[A-Z] *)(?=.*\1)"
    Text = StrReverse(Text) & " "
    If .test(Text) Then UniqueSubject = StrReverse(.Replace(Text & " ", ""))
  End With
End Function
 
Upvote 0
Xin các Bác giúp đỡ tiếp :
dữ liệu: S1=AnhB1.B2.Em.C1.C2; S2=AnhB1.B2.B3.EmC1.C2.C3 làm sao cho biết KQ tăng: AnhB3, EmC3
S1=AnhB1.B2.B3.EmC1.C2.C3; S2=AnhB1.B2.Am.C1.C2 làm sao cho biết KQ Giảm: AnhB3, EmC3
Xin cám ơn!
 
Upvote 0
anhphuquocvn
Bác có thể sử dụng Biểu thức chính quy


--------------------------
Mã:
Function UniqueSubject(ByVal Text$)
  With VBA.CreateObject("VBScript.RegExp")
    .Global = True: .ignorecase = False
    .Pattern = "([a-z]+[A-Z] *)(?=.*\1)"
    Text = StrReverse(Text) & " "
    If .test(Text) Then UniqueSubject = StrReverse(.Replace(Text & " ", ""))
  End With
End Function
Test thấy đúng mà vẫn không hiểu cái này là cái gì
 
Upvote 0
Test thấy đúng mà vẫn không hiểu cái này là cái gì
Phân tích ([a-z]+[A-Z] *)(?=.*\1) ra là thầy hiểu:

Hai dấu ngoặc tròn () để phân biệt một nhóm
(?=) trong biểu thức chính quy có nghĩa là có nhưng không bắt lấy nhóm này.
\1 có nghĩa là sao chép lại những gì nhóm 1 bắt được chuỗi, ([a-z]+[A-Z] *) chính là nhóm 1

Phân tích (?=.*\1): bất kỳ ký tự nào phía trước kết hợp với nhóm 1 thì không lấy.
Vì \1 không bao giờ nằm trước nhóm sao chép nên phải đảo ngược chuỗi để bắt nhóm.
Phân tích ([a-z]+[A-Z] *) : bắt lấy các ký tự Thường từ 1 đến n lần, theo sau là 1 ký tự Hoa, theo sau 0 đến n ký tự ký tự dấu cách.


Hàm sử dụng Phương thức Replace của RegEx để tách chuỗi:
Hàm này sẽ thay thế các ký tự bắt được thành một chuỗi khác, nếu có cú pháp thì thay thế theo cú pháp.


Khi tách chuỗi:
TinA1. TinA2. TinA3. LyA1. LyA2. LyA3. HoaA1. HoaA2.
Sau khi đảo chuỗi:
.2AaoH .1AaoH .3AyL .2AyL .1AyL .3AniT .2AniT .1AniT

Bắt chuỗi:
"aoH .1AaoH"
Nhóm 1 = "aoH "
Bất kì ký tự nào kết hợp với nhóm 1 = ".1AaoH"
Repalce RegEx sẽ xóa Nhóm 1 "aoH "
Giữ ".1AaoH"

Cứ thế cho đến khi kết thúc chuỗi và đảo chuỗi ngược lại để trả kết quả.
 
Upvote 0
Phân tích ([a-z]+[A-Z] *)(?=.*\1) ra là thầy hiểu:

Hai dấu ngoặc tròn () để phân biệt một nhóm
(?=) trong biểu thức chính quy có nghĩa là có nhưng không bắt lấy nhóm này.
\1 có nghĩa là sao chép lại những gì nhóm 1 bắt được chuỗi, ([a-z]+[A-Z] *) chính là nhóm 1

Phân tích (?=.*\1): bất kỳ ký tự nào phía trước kết hợp với nhóm 1 thì không lấy.
Vì \1 không bao giờ nằm trước nhóm sao chép nên phải đảo ngược chuỗi để bắt nhóm.
Phân tích ([a-z]+[A-Z] *) : bắt lấy các ký tự Thường từ 1 đến n lần, theo sau là 1 ký tự Hoa, theo sau 0 đến n ký tự ký tự dấu cách.


Hàm sử dụng Phương thức Replace của RegEx để tách chuỗi:
Hàm này sẽ thay thế các ký tự bắt được thành một chuỗi khác, nếu có cú pháp thì thay thế theo cú pháp.


Khi tách chuỗi:
TinA1. TinA2. TinA3. LyA1. LyA2. LyA3. HoaA1. HoaA2.
Sau khi đảo chuỗi:
.2AaoH .1AaoH .3AyL .2AyL .1AyL .3AniT .2AniT .1AniT

Bắt chuỗi:
"aoH .1AaoH"
Nhóm 1 = "aoH "
Bất kì ký tự nào kết hợp với nhóm 1 = ".1AaoH"
Repalce RegEx sẽ xóa Nhóm 1 "aoH "
Giữ ".1AaoH"

Cứ thế cho đến khi kết thúc chuỗi và đảo chuỗi ngược lại để trả kết quả.
RegEx này khó quá bác ạ!
 
Upvote 0
Phân tích ([a-z]+[A-Z] *)(?=.*\1) ra là thầy hiểu:

Hai dấu ngoặc tròn () để phân biệt một nhóm
(?=) trong biểu thức chính quy có nghĩa là có nhưng không bắt lấy nhóm này.
\1 có nghĩa là sao chép lại những gì nhóm 1 bắt được chuỗi, ([a-z]+[A-Z] *) chính là nhóm 1

Phân tích (?=.*\1): bất kỳ ký tự nào phía trước kết hợp với nhóm 1 thì không lấy.
Vì \1 không bao giờ nằm trước nhóm sao chép nên phải đảo ngược chuỗi để bắt nhóm.
Phân tích ([a-z]+[A-Z] *) : bắt lấy các ký tự Thường từ 1 đến n lần, theo sau là 1 ký tự Hoa, theo sau 0 đến n ký tự ký tự dấu cách.


Hàm sử dụng Phương thức Replace của RegEx để tách chuỗi:
Hàm này sẽ thay thế các ký tự bắt được thành một chuỗi khác, nếu có cú pháp thì thay thế theo cú pháp.


Khi tách chuỗi:
TinA1. TinA2. TinA3. LyA1. LyA2. LyA3. HoaA1. HoaA2.
Sau khi đảo chuỗi:
.2AaoH .1AaoH .3AyL .2AyL .1AyL .3AniT .2AniT .1AniT

Bắt chuỗi:
"aoH .1AaoH"
Nhóm 1 = "aoH "
Bất kì ký tự nào kết hợp với nhóm 1 = ".1AaoH"
Repalce RegEx sẽ xóa Nhóm 1 "aoH "
Giữ ".1AaoH"

Cứ thế cho đến khi kết thúc chuỗi và đảo chuỗi ngược lại để trả kết quả.
Cám ơn bạn đã phân tích ..... làm mình thêm tí xíu về việc hiểu về cái này!
cái này (RegEx) thiệt là mình vẫn chưa hình dung được hết về nó!!
 
Upvote 0
Xin các Bác giúp đỡ tiếp, nhất là Bác : HeSanbi Giỏi quá
dữ liệu: S1=AnhB1.B2.Em.C1.C2; S2=AnhB1.B2.B3.EmC1.C2.C3 làm sao cho biết KQ tăng: AnhB3, EmC3
S1=AnhB1.B2.B3.EmC1.C2.C3; S2=AnhB1.B2.Am.C1.C2 làm sao cho biết KQ Giảm: AnhB3, EmC3
Xin cám ơn!
 
Upvote 0
Xin các Bác giúp đỡ tiếp :
dữ liệu: S1=AnhB1.B2.Em.C1.C2; S2=AnhB1.B2.B3.EmC1.C2.C3 làm sao cho biết KQ tăng: AnhB3, EmC3
S1=AnhB1.B2.B3.EmC1.C2.C3; S2=AnhB1.B2.Am.C1.C2 làm sao cho biết KQ Giảm: AnhB3, EmC3
Xin cám ơn!

Tôi chỉ giải thêm bài này giúp bác nữa thôi nhé.

------------------------
JavaScript:
Sub CheckOrderUP_test()
  Debug.Print CheckOrderUP("AnhB1.B2.EmC1.C2", "AnhB1.B2.B3.Em.C1.C2.C3")
  Debug.Print CheckOrderUP("AnhB1.B2.B3.EmC1.C2.C3", "AnhB1.B2.EmC1.C2")
End Sub
Function CheckOrderUP(ByVal Text1$, ByVal Text2$)
  Dim M1, M2, M3, N1, N2, S, P$
  With VBA.CreateObject("VBScript.RegExp")
    .Global = True: .IgnoreCase = False
    P = "(?:[A-Z]+\d+(?:\.|$))"
    .Pattern = "([A-Z][a-z]+)\.?(" & P & "+)"
    If Not .Test(Text1) Or Not .Test(Text2) Then Exit Function
    Set M1 = .Execute(Text1): Set M2 = .Execute(Text2)
    For Each N1 In M1
      For Each N2 In M2
        .Pattern = N2.SubMatches(0) & "\.*" & N2.SubMatches(1) & "\.*(" & P & "+)"
        If .Test(N1) Then
          S = S & IIf(S = "", "KQ Gi" & ChrW(7843) & "m ", ",") & N1.SubMatches(0) & .Execute(N1)(0).SubMatches(0)
        Else
          .Pattern = N1.SubMatches(0) & "\.*" & N1.SubMatches(1) & "\.*(" & P & "+)"
          If .Test(N2) Then
            S = S & IIf(S = "", "KQ t" & ChrW(259) & "ng ", ",") & N2.SubMatches(0) & .Execute(N2)(0).SubMatches(0)
          End If
        End If
      Next
    Next
  End With
  CheckOrderUP = Replace(S, ".,", ",")
End Function
 
Upvote 0
Những bài dạng này quan trọng nhất là code tổng quát. Tôi nghĩ nên dùng vòng lặp kiểm tra từng phần tử, thớt thử xem sao.
Mã:
Function Gop(ByVal sStr As String) As String
Dim aTmp As Variant, i As Long, sPattern As String
sStr = Tach(sStr)
aTmp = Split(sStr, ".")
RemoveSpace aTmp
For i = LBound(aTmp, 1) To UBound(aTmp, 1)
    If aTmp(i) <> "" Then
        sPattern = Left(aTmp(i), Len(aTmp(i)) - 2) & "?#"
        aTmp(i) = " " & aTmp(i) & "."
        For j = i + 1 To UBound(aTmp, 1)
            If aTmp(j) Like sPattern Then
                aTmp(i) = aTmp(i) & Right(aTmp(j), 2) & "."
                aTmp(j) = ""
            End If
        Next
    End If
Next
Gop = Mid(Join(aTmp, ""), 2)
End Function
Mã:
Function Tach(ByVal sStr As String) As String
Dim aTmp As Variant, i As Long, sPattern As String
aTmp = Split(sStr, ".")
RemoveSpace aTmp
For i = LBound(aTmp, 1) To UBound(aTmp, 1)
    If aTmp(i) <> "" And Not aTmp(i) Like "?#" Then
        sPattern = Left(aTmp(i), Len(aTmp(i)) - 2)
        aTmp(i) = " " & aTmp(i) & "."
        For j = i + 1 To UBound(aTmp, 1)
            If aTmp(j) Like "?#" Then
                aTmp(i) = aTmp(i) & " " & sPattern & aTmp(j) & "."
                aTmp(j) = ""
            Else
                Exit For
            End If
        Next
    End If
Next
Tach = Mid(Join(aTmp, ""), 2)
End Function
Mã:
Function Tru(ByVal sStr1 As String, ByVal sStr2 As String) As String
Dim aTmp As Variant, i As Long
sStr1 = ". " & Replace(Tach(sStr1), ".", "..")
sStr2 = Tach(sStr2)
aTmp = Split(sStr2, ".")
RemoveSpace aTmp
For i = LBound(aTmp, 1) To UBound(aTmp, 1)
    sStr1 = Replace(sStr1, ". " & aTmp(i) & ".", "")
Next
Tru = Gop(Replace(sStr1, "..", "."))
End Function
Mã:
Private Sub RemoveSpace(ByRef Arr As Variant)
Dim i As Long
For i = LBound(Arr, 1) To UBound(Arr, 1)
    Arr(i) = Trim(Arr(i))
Next
End Sub
 

File đính kèm

  • GPE.xlsm
    19.2 KB · Đọc: 7
Upvote 0
Nhìn cái yêu cầu đầu ra muốn bắt bịnh rồi. Loại yêu cầu này đến đâu chữa đến đó chứ hơi đâu mà tổng quát.
Tổng quát ở mức độ nào đó thôi. Ví dụ, ban đầu có TinA1. TinA2. TinA3. LyA1. LyA2. LyA3. HoaA1. HoaA2., bây giờ muốn thêm TinA4 thì thêm vào cuối vẫn được, không lẽ bắt buộc phải thêm đúng chỗ.
 
Upvote 0
Tôi xin chân thành cảm ơn các AC đã giúp đỡ tận tình!
Chúc AC mạnh khỏe và Thành công!
 
Upvote 0
Web KT

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

Back
Top Bottom