在 Go 中,字符串被视为字节切片而不是字符序列。这使得执行字符级操作(如反转字符串)变得具有挑战性。
让我们考虑以下场景:我们有几个长度不同的随机字符字符串(100、 200、300、400 和 500)。我们想要反转每个字符串的字符。
尝试将字符直接分配给字符串中的不同索引会导致错误,因为 Go 不允许直接字符级字符串赋值。
Andrew Sellers 在他的要点中提供了一种创新方法,用于处理组合变音标记 (CDM) 和其他复杂 Unicode 字符的 Unicode。
他引入了一种检测和保留 CDM 顺序的技术,CDM 是复杂 Unicode 块的一部分,会影响字符串中的字符组合。
解决方案涉及迭代字符串以相反的顺序并使用范围表识别 CDM。 CDM 被存储,然后与常规字符组合,然后将其添加到反向数组中。
对于表情符号和修饰符等字符,该方法需要特别考虑以保留元素的顺序以及组合字形的正确表示。
以下是基于 Andrew Sellers 方法的代码片段:
<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>
以上是如何在 Go 中反转字符串,处理 Unicode 组合变音符号?的详细内容。更多信息请关注PHP中文网其他相关文章!