如何在GO中操纵字符串以反转它们?

时间:2018-11-11 00:41:36

标签: string go inversion reversion

我正在尝试反转一个字符串,但是在处理字符时遇到了麻烦。与C不同,GO将字符串视为字节向量,而不是字符,在这里称为符文。我尝试进行一些类型转换来完成分配,但是到目前为止我还做不到。

这里的想法是生成5个具有100、200、300、400和500大小的随机字符的字符串,然后反转它们的字符。我能够轻松地使用C,但是在GO语言中,该语言返回了一个错误,指出无法执行分配。

 func inverte() {
    var c = "A"
    var strs, aux string

    rand.Seed(time.Now().UnixNano())
    // Gera 5 vetores de 100, 200, 300, 400, e 500 caracteres
    for i := 1; i < 6; i++ {
        strs = randomString(i * 100)
        fmt.Print(strs)

        for i2, j := 0, len(strs); i2 < j; i2, j = i+1, j-1 {
           aux = strs[i2]
           strs[i2] = strs[j]
           strs[j] = aux
       }
   }
}

2 个答案:

答案 0 :(得分:3)

如果您想考虑unicode combining characters,请Andrew Sellers参加in this gist

首先列出所有组合的变音标记(CDM)的Unicode block range

var combining = &unicode.RangeTable{
    R16: []unicode.Range16{
        {0x0300, 0x036f, 1}, // combining diacritical marks
        {0x1ab0, 0x1aff, 1}, // combining diacritical marks extended
        {0x1dc0, 0x1dff, 1}, // combining diacritical marks supplement
        {0x20d0, 0x20ff, 1}, // combining diacritical marks for symbols
        {0xfe20, 0xfe2f, 1}, // combining half marks
    },
}

然后,您可以依次读取初始字符串的符文:

sv := []rune(s)

但是,如果按反向的顺序进行操作,则会遇到组合变音标记(CDM) 第一为了保留其顺序,不撤消

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)
        }

(请注意,%c组合符周围的空格:'%c'没有空格,这意味着将标记与第一个'ͤ':组合在一起,而不是'''。我尝试使用{ {3}} \u034F,但无效)

如果最终遇到常规符文,则需要与这些CDM结合,然后再将其添加到反向最终符文阵列中。

        } 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)
        }

表情符号变得更加复杂,例如最近出现的修饰符,例如CGJ Combining Grapheme Joiner,肤色Medium-Dark Skin Tone上的类型5。
如果忽略该选项,则反向“ ?????‍?????‍⚖️”将给出“ ️⚖‍?????‍??”,从而使最后两个表情符号上的肤色消失。

??‍?单独是(来自Fitzpatrick Scale):

那些应该保持完全相同的顺序。

别让我开始使用red hair (1f9b0)(200D),它会迫使ZERO WIDTH JOINER的相邻字符(例如阿拉伯字符或受支持的表情符号)结合在一起。可以用来组成顺序组合的表情符号。

??‍⚖️是由两个表情符号组成的实际 one 字形。 应该倒置。
下面的程序正确地检测到“零宽度连接符”,并且反转其组合的表情符号。


Wisdom/Awesome-Unicode中的完整示例。

Reverse 'Hello, World' => 'dlroW ,olleH'
Reverse '??⃠?' => '??⃠?'
Reverse '??‍?????‍⚖️' => '??‍⚖️????‍?'
Reverse 'aͤoͧiͤ  š́ž́ʟ́' => 'ʟ́ž́š́  iͤoͧaͤ'
Reverse 'H̙̖ell͔o̙̟͚͎̗̹̬ ̯W̖͝ǫ̬̞̜rḷ̦̣̪d̰̲̗͈' => 'd̰̲̗͈ḷ̦̣̪rǫ̬̞̜W̖͝ ̯o̙̟͚͎̗̹̬l͔leH̙̖'

答案 1 :(得分:2)

正如您正确识别的go strings are immutable,因此您无法在给定索引处分配符文/字符值。

与其代替就地反转字符串,还必须在字符串中创建一个符文副本,然后反转它们,然后返回结果字符串。

例如(Go Playground):

func reverse(s string) string {
  rs := []rune(s)
  for i, j := 0, len(rs)-1; i < j; i, j = i+1, j-1 {
    rs[i], rs[j] = rs[j], rs[i]
  }
  return string(rs)
}

func main() {
  fmt.Println(reverse("Hello, World!"))
  // !dlroW ,olleH
  fmt.Println(reverse("Hello, 世界!"))
  // !界世 ,olleH
}

由于Unicode的复杂性(例如combining diacritical marks),这种方法存在一些问题,但这会让您入门。