TrimRight-LastIndex


🧩 1. Hàm TrimRight(s, cutset string) string

📌 Mục tiêu:

Cắt bỏ các ký tự trong cutset bên phải của chuỗi s.

🧠 Ý tưởng:

Duyệt từ cuối chuỗi về đầu, dừng lại khi gặp ký tự không thuộc cutset.

✅ Source code (rút gọn từ Go standard library strings/trim.go):

func TrimRight(s, cutset string) string {
    return TrimRightFunc(s, func(r rune) bool {
        return strings.ContainsRune(cutset, r)
    })
}

➡️ Tức là TrimRight được xây dựng dựa trên TrimRightFunc.


🔍 TrimRightFunc hoạt động ra sao?

func TrimRightFunc(s string, f func(rune) bool) string {
    i := len(s)
    for i > 0 {
        r, size := utf8.DecodeLastRuneInString(s[:i])
        if !f(r) {
            break
        }
        i -= size
    }
    return s[:i]
}

💡 Phân tích:

  • Duyệt từ cuối chuỗi s.

  • Dùng utf8.DecodeLastRuneInString() để decode rune cuối (hỗ trợ Unicode).

  • Nếu rune này thuộc cutset (qua hàm f), tiếp tục cắt.

  • Trả về chuỗi từ đầu đến vị trí dừng lại.


🧩 2. Hàm LastIndex(s, sep string) int

📌 Mục tiêu:

Tìm vị trí xuất hiện cuối cùng của chuỗi con sep trong chuỗi s.

🧠 Ý tưởng:

Duyệt từ phía cuối chuỗi s, so sánh từng đoạn con với sep.

✅ Source code (rút gọn từ strings/strings.go):

func LastIndex(s, sep string) int {
    n := len(sep)
    switch {
    case n == 0:
        return len(s)
    case n == 1:
        c := sep[0]
        for i := len(s) - 1; i >= 0; i-- {
            if s[i] == c {
                return i
            }
        }
        return -1
    case n == len(s):
        if sep == s {
            return 0
        }
        return -1
    case n > len(s):
        return -1
    }

    // Trường hợp general: duyệt từng đoạn con
    for i := len(s) - n; i >= 0; i-- {
        if s[i:i+n] == sep {
            return i
        }
    }
    return -1
}

📌 Tóm tắt cách tự viết lại (custom implementation):

🧪 TrimRight phiên bản đơn giản:

func MyTrimRight(s string, cutset string) string {
    i := len(s)
    for i > 0 {
        if strings.ContainsRune(cutset, rune(s[i-1])) {
            i--
        } else {
            break
        }
    }
    return s[:i]
}

🧪 LastIndex phiên bản đơn giản:

func MyLastIndex(s, sep string) int {
    n := len(sep)
    if n == 0 {
        return len(s)
    }
    for i := len(s) - n; i >= 0; i-- {
        if s[i:i+n] == sep {
            return i
        }
    }
    return -1
}

✅ Kết luận:

  • TrimRight được cài bằng TrimRightFunc, hoạt động bằng cách decode rune ngược từ cuối, và cắt nếu còn trong cutset.

  • LastIndex dùng một vòng lặp để so khớp chuỗi con từ phải sang trái, tối ưu cho cả chuỗi 1 ký tự hoặc chuỗi dài.

  • Cả 2 hàm đều có khả năng unicode-safe, xử lý cả kí tự nhiều byte nhờ dùng utf8.

Last updated