How to reverse a string in Go?

前端 未结 28 1990
天涯浪人
天涯浪人 2020-12-04 06:45

How can we reverse a simple string in Go?

28条回答
  •  误落风尘
    2020-12-04 07:28

    I wrote the following Reverse function which respects UTF8 encoding and combined characters:

    // Reverse reverses the input while respecting UTF8 encoding and combined characters
    func Reverse(text string) string {
        textRunes := []rune(text)
        textRunesLength := len(textRunes)
        if textRunesLength <= 1 {
            return text
        }
    
        i, j := 0, 0
        for i < textRunesLength && j < textRunesLength {
            j = i + 1
            for j < textRunesLength && isMark(textRunes[j]) {
                j++
            }
    
            if isMark(textRunes[j-1]) {
                // Reverses Combined Characters
                reverse(textRunes[i:j], j-i)
            } 
    
            i = j
        }
    
        // Reverses the entire array
        reverse(textRunes, textRunesLength)
    
        return string(textRunes)
    }
    
    func reverse(runes []rune, length int) {
        for i, j := 0, length-1; i < length/2; i, j = i+1, j-1 {
            runes[i], runes[j] = runes[j], runes[i]
        }
    }
    
    // isMark determines whether the rune is a marker
    func isMark(r rune) bool {
        return unicode.Is(unicode.Mn, r) || unicode.Is(unicode.Me, r) || unicode.Is(unicode.Mc, r)
    }
    

    I did my best to make it as efficient and readable as possible. The idea is simple, traverse through the runes looking for combined characters then reverse the combined characters' runes in-place. Once we have covered them all, reverse the runes of the entire string also in-place.

    Say we would like to reverse this string bròwn. The ò is represented by two runes, one for the o and one for this unicode \u0301a that represents the "grave".

    For simplicity, let's represent the string like this bro'wn. The first thing we do is look for combined characters and reverse them. So now we have the string br'own. Finally, we reverse the entire string and end up with nwo'rb. This is returned to us as nwòrb

    You can find it here https://github.com/shomali11/util if you would like to use it.

    Here are some test cases to show a couple of different scenarios:

    func TestReverse(t *testing.T) {
        assert.Equal(t, Reverse(""), "")
        assert.Equal(t, Reverse("X"), "X")
        assert.Equal(t, Reverse("b\u0301"), "b\u0301")
        assert.Equal(t, Reverse("

提交回复
热议问题