In Go, strings are treated as byte slices rather than character sequences. This can make it challenging to perform character-level operations like reversing strings.
Let's consider the following scenario: we have several strings of random characters with varying lengths (100, 200, 300, 400, and 500). We want to invert the characters of each string.
Attempts to assign characters directly to different indices in the string result in an error, as Go does not allow direct character-level assignment to strings.
Andrew Sellers provides an innovative approach in his gist that handles Unicode combining diacritical marks (CDMs) and other complex Unicode characters.
He introduces a technique to detect and preserve the order of CDMs, which are part of a complex Unicode block that affects combining characters within a string.
The solution involves iterating through the string in reverse order and identifying CDMs using a range table. CDMs are stored, and then combined with regular characters before adding them to the reversed array.
For characters like emojis and modifiers, the approach requires special consideration to preserve the order of elements and the correct representation of composed glyphs.
Here's a code snippet based on Andrew Sellers' approach:
<code class="go">package main import ( "fmt" "os" "runtime" "unicode" ) func main() { var stringsToReverse = []string{"Hello, World", "??⃠?", "???????⚖️", "aͤoͧiͤ š́ž́ʟ́", "H̙̖ell͔o̙̟͚͎̗̹̬ ̯W̖͝ǫ̬̞̜rḷ̦̣̪d̰̲̗͈"} for _, s := range stringsToReverse { fmt.Printf("Reverse '%s' => '%s'\n", s, ReverseString(s)) } fmt.Printf("Memory usage: %d bytes\n", runtime.MemStats.Alloc) os.Exit(0) } // ReverseString reverses the characters in a string, handling Unicode combining diacritical marks func ReverseString(s string) string { sv := []rune(s) cv := make([]rune, 0) rv := make([]rune, 0) for ix := len(sv) - 1; ix >= 0; ix-- { r := sv[ix] if unicode.In(r, combining) { cv = append(cv, r) fmt.Printf("Detect combining diacritical mark ' %c'\n", r) } else { rrv := make([]rune, 0, len(cv)+1) rrv = append(rrv, r) rrv = append(rrv, cv...) fmt.Printf("regular mark '%c' (with '%d' combining diacritical marks '%s') => '%s'\n", r, len(cv), string(cv), string(rrv)) rv = append(rv, rrv...) cv = make([]rune, 0) } } return string(rv) }</code>
The above is the detailed content of How to Reverse a String in Go, Handling Unicode Combining Diacritical Marks?. For more information, please follow other related articles on the PHP Chinese website!