Tách chuỗi vào mảng (array) có điều kiện

Liên hệ QC
Tôi tuân thủ nội quy khi đăng bài

Baby_Shark

Thành viên mới
Tham gia
23/9/22
Bài viết
7
Được thích
1
Chào Anh/Chị GPE,
Em có nhiều ô, mỗi ô là một đoạn văn bản (có thể ngắn có thể dài, dài tức là hơn 800 ký tự). Do code sau đó bên công ty em cần xử lý chuỗi này, nhưng nếu lớn hơn 800 ký tự thì code không hoạt động, nên em cần chia nhỏ chuỗi đưa vào mảng để xử lý cho phần sau.
Chuỗi văn bản có ý nghĩa, vì thế em không thể cắt đúng 800 ký tự để đưa vào mảng được mà em sẽ cắt chuỗi ưu tiên theo ký tự xuống dòng (char(10) - em thấy theo ký tự này có lẽ độ chính xác cao nhất), nếu sau khi tách bằng char(10) mà chuỗi vẫn dài hơn 800 thì cắt chuỗi theo ký tự ". " (dấu chấm kèm 1 dấu space). Nếu cắt theo dấu ". " mà vẫn vượt thì trả về lỗi và không xử lý nữa.
Điều kiện đi kèm là chuỗi con sau khi tách phải có chiều dài gần 800 ký tự nhất có thể, bởi nếu không thì có thể dẫn tới chia rất nhiều chuỗi con, kéo theo code sau đó phải xử lý nhiều hơn (Kết quả mong muốn là trả vào một mảng các chuỗi nhỏ hơn 800)
Mong Anh/Chị GPE giúp đỡ. Em có đính kèm file một số chữ cho anh chị dễ thử
Em cảm ơn!
 

File đính kèm

  • Vidu.xlsm
    9.4 KB · Đọc: 14
Trước tiên thử xét nếu len của chuỗi bán đầu lớn hơn 800 thì sẽ chia ra làm 2 mảng. Mảng 1 là 800kí tự. Mảng 2 là số kí tự còn lại. Rồi tiếp tục làm những việc bạn muốn xem
 
Upvote 0
Trước tiên thử xét nếu len của chuỗi bán đầu lớn hơn 800 thì sẽ chia ra làm 2 mảng. Mảng 1 là 800kí tự. Mảng 2 là số kí tự còn lại. Rồi tiếp tục làm những việc bạn muốn xem
Cảm ơn anh đã hỗ trợ, ý em muốn là chia theo mốc tối đa 800 ký tự, tuy nhiên khi tách ra thì nó phải nguyên câu. Tức là mỗi vị trí trong mảng là đầy đủ một câu, nhưng giả sử câu đó dài 1600 ký tự mà có nhiều ký tự xuống dòng thì cũng chỉ cắt một vài chỗ để đáp ứng gần 800 ký tự nhất thôi. Em không muốn chia nhỏ theo toàn bộ ký tự xuống dòng. Mảng trả về càng nhiều thì phần sau đó càng phải xử lý nhiều, nên em không mong muốn như vậy
 
Upvote 0
Bạn có thể thử phương án như sau:
- Nếu văn bản ít hơn 800 ký tự thì không cần tách
- Nếu văn bản lớn hơn 800 ký tự thì tìm từ vị trí 800 ngược về đầu ký tự ".", nếu thấy thì tách văn bản thành 2 phần.
phần 1 từ đầu văn bản đến vị trí ký tự ".", phần 2 là đoạn còn lại
- Làm tương tự cho đến khi không còn phần nào lớn hơn 800 ký tự thì ngừng lại

Lưu ý: trong trường hợp có đoạn văn bản nào trên 800 ký tự mà k có dấu chấm thì sẽ k làm như vậy được. Bạn có thể thay tìm theo ký tự "." bằng ký tự khác cho phù hợp nhất
 
Upvote 0
Bạn có thể thử phương án như sau:
- Nếu văn bản ít hơn 800 ký tự thì không cần tách
- Nếu văn bản lớn hơn 800 ký tự thì tìm từ vị trí 800 ngược về đầu ký tự ".", nếu thấy thì tách văn bản thành 2 phần.
phần 1 từ đầu văn bản đến vị trí ký tự ".", phần 2 là đoạn còn lại
- Làm tương tự cho đến khi không còn phần nào lớn hơn 800 ký tự thì ngừng lại

Lưu ý: trong trường hợp có đoạn văn bản nào trên 800 ký tự mà k có dấu chấm thì sẽ k làm như vậy được. Bạn có thể thay tìm theo ký tự "." bằng ký tự khác cho phù hợp nhất
Cảm ơn anh giúp đỡ, về hướng làm anh nói thì em có thể hình dung được. Nhưng để hiện thực vào code thì em còn yếu lắm. Mong anh có thể giúp đỡ thêm
 
Upvote 0
Cảm ơn anh giúp đỡ, về hướng làm anh nói thì em có thể hình dung được. Nhưng để hiện thực vào code thì em còn yếu lắm. Mong anh có thể giúp đỡ thêm

Bạn thử dùng hàm này xem có được không?

Mã:
Function Tach_vb(ByVal S As String)
    Dim arr, i As Long, n As Long
    
    If Len(S) <= 800 Then 'ky tu <=800
        Tach_vb = S
    Else
        ReDim arr(1 To 1)
        
        Do While Len(S) > 800
            i = InStrRev(S, ".", 800) 'Tim vi tri ky tu . tu vi tri 800 ve truoc
            If i = 0 Then Tach_vb = "Loi": Exit Function 'Neu trong 800 ky tu khong co dau .
            'Dinh dang mang
            n = n + 1
            ReDim Preserve arr(1 To n)
            'Chuoi 1
            arr(n) = Left(S, i)
            'Chuoi 2
            S = Right(S, Len(S) - i)
        Loop
        'Neu chuoi cung co ky tu thi ghi not vao mang
        If Len(S) > 0 Then
            n = n + 1
            ReDim Preserve arr(1 To n)
            arr(n) = S
        End If
        Tach_vb = arr
    End If
End Function
 
Upvote 0
Bạn thử dùng hàm này xem có được không?

Mã:
Function Tach_vb(ByVal S As String)
    Dim arr, i As Long, n As Long
   
    If Len(S) <= 800 Then 'ky tu <=800
        Tach_vb = S
    Else
        ReDim arr(1 To 1)
       
        Do While Len(S) > 800
            i = InStrRev(S, ".", 800) 'Tim vi tri ky tu . tu vi tri 800 ve truoc
            If i = 0 Then Tach_vb = "Loi": Exit Function 'Neu trong 800 ky tu khong co dau .
            'Dinh dang mang
            n = n + 1
            ReDim Preserve arr(1 To n)
            'Chuoi 1
            arr(n) = Left(S, i)
            'Chuoi 2
            S = Right(S, Len(S) - i)
        Loop
        'Neu chuoi cung co ky tu thi ghi not vao mang
        If Len(S) > 0 Then
            n = n + 1
            ReDim Preserve arr(1 To n)
            arr(n) = S
        End If
        Tach_vb = arr
    End If
End Function
Cảm ơn anh nhiều, anh có thể xem thêm giúp em, theo điều kiện ban đầu em có nói là xét ký tự xuống dòng trước. Nếu nó thỏa thì thôi, nếu không thỏa mới xét tới ". " đó anh
 
Upvote 0
Cảm ơn anh nhiều, anh có thể xem thêm giúp em, theo điều kiện ban đầu em có nói là xét ký tự xuống dòng trước. Nếu nó thỏa thì thôi, nếu không thỏa mới xét tới ". " đó anh
Theo như ví dụ của bạn thì nếu cắt theo dấu "." gần 800 ký tự nhất thì sẽ thành 3 đoạn nhỏ, nếu cắt theo dấu xuống dòng rồi mới tới dấu "." thì sẽ là 4 đoạn. Vậy bạn sẽ ưu tiên theo cách nào? và code của bạn có xử lý được dấu xuống dòng hay không mà phải cắt như vậy?
 
Upvote 0
Theo như ví dụ của bạn thì nếu cắt theo dấu "." gần 800 ký tự nhất thì sẽ thành 3 đoạn nhỏ, nếu cắt theo dấu xuống dòng rồi mới tới dấu "." thì sẽ là 4 đoạn. Vậy bạn sẽ ưu tiên theo cách nào? và code của bạn có xử lý được dấu xuống dòng hay không mà phải cắt như vậy?
Em vẫn ưu tiên cắt theo xuống dòng trước anh ạ. Đôi khi chấp nhận nhiều hơn tí nhưng độ chính xác của nó cao hơn cắt theo ". " . Vì dấu ". " đôi khi có những dữ liệu khác có thể chứa nó trong một câu
 
Upvote 0
Làm tạm cái này:
Nếu chuỗi ở ô A1, Từ B1 sang C1, D1,... lần lượt tách chuỗi
Tại ô B1 dùng công thức:
Mã:
=IFERROR(tach($A1:A1),"")
copy sang phải

PHP:
Option Explicit
Function tach(ByVal rng As Range)
Dim i&, j&, st1 As String, st2 As String, cell As Range, max&
Do
    j = j + 1: i = 0
    If j = 1 Then st1 = rng.Cells(1, 1).Value & ". XXX"
    Do While i <= 800
        i = i + 1
        If Mid(st1, i, 1) = Chr(10) Then
            max = i
            Exit Do
        End If
        If Mid(st1, i, 2) = ". " Then max = i
    Loop
    st2 = Left(st1, max): st1 = Mid(st1, max + 1, Len(st1) - max - 1)
Loop Until j >= rng.Cells.Count
tach = st2
End Function
 

File đính kèm

  • Vidu.xlsm
    20.4 KB · Đọc: 8
Upvote 0
Tôi không mở file xlsm cho nên không biết kết quả bạn muốn ra sao.
Tuy nhiên, tôi chưa hiểu cách bên đầu kia đọc chuỗi. Làm cách nào nó biết được chuỗi trước đó là ký tự Chr(10) hay Chr(46)+Chr(32) ". ".

Bạn làm việc với bên nhận đầu ra của mình thì cũng nên tím hiểu cho kỹ, như thế nào thì họ đọc được.

Ví dụ bên kia chấp nhận ||| là ký tự chr(10) trước khi tách, và || là ký tự ". " trước khi tách thì giải thuật như sau:

1. Replace chr(10) với "|||##", ". " với "||##"
2. Split theo ký tự "##"
3. Chép vào mảng 2 chiều
4. Chép vao range
5. Bên kia chỉ cần đọc từng dòng và tự hiểu.
6. Hết
Có thể sẽ ra mảng rất lớn. Nhưng thời buổi RAM cả đống như bi giờ thì mảng lớn chả sao cả.
Số dòng cũng khá lơn. Nhưng bù lại, dữ liệu sạch sẽ, đồng bộ.
 
Upvote 0
Web KT

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

Back
Top Bottom