【问题标题】:Reverse range over a string反转字符串范围
【发布时间】:2022-01-04 20:51:18
【问题描述】:

如何在遍历 string 的单个字符时“反转范围”?
例如,给定s := "some string \u1222 whatever" - 我想做类似的事情:

for i, v := ~reverse~ range s {
}

请注意,我对通过标准库提供的解决方案感兴趣,而不必自己编写函数。我知道大量现有的图书馆可以做到这一点,但这无关紧要。此外 - 我不能使用 len(s) 并这样做:

for i := len(s) - 1; i >= 0; i-- {
}

因为在 Go 中内置的 len 函数只返回字符串中的字节数(不适用于非 ASCII 字符串)。我也做不到len(s) - k - 1,其中krange指令提供的索引,由于上述原因。


UPD1: 可以对utf-8runes 进行反向(从右到左)查找,因为我们可以通过每个字节或字节组的高位轻松识别runes。来自The Go Programming Language书:

如您所见,我们可以从最后一个字节开始,最多需要向左扫描 4 个字节才能得到rune

【问题讨论】:

  • 基本上不可能“反转”任意 Unicode 字符串。
  • 问题不是如何“反转”,而是如何以相反的顺序访问每个单独的 utf-8 字符。
  • 好吧,让我改写一下:基本上不可能“以相反的顺序访问每个单独的 utf-8 字符 [任意 Unicode 字符串]”。真的。将字符和 ltr/rtl 以及可能更多我什至不知道的组合使这项任务不可能。问题不在于“反转”,而在于“字符”。
  • @Volker,我在我的问题中添加了一个更新部分,我解释了如何以相反的顺序访问 utf-8 字符。在 Go 中,utf-8 符文被分组为 1、2、3、4 个字节,每个组的字节序列对于该组的任何字符都具有相同的高阶位。因此,从最后一个字节开始,最多查找 4 个字节会给我们一个 utf-8 字符。顺便说一句,这就是 DecodeLastRune 的工作原理:cs.opensource.google/go/go/+/refs/tags/go1.17.3:src/unicode/…
  • 您将 Unicode 代码点与“字符”混为一谈。你是对的,以相反的顺序访问代码点是微不足道的。但这不是“字符”。

标签: string loops go


【解决方案1】:

最简单的解决方案是将string 转换为[]rune,这样您就可以对其进行迭代,但索引“向后”(或使用向下循环):

rs := []rune(s)
max := len(rs) - 1
for i := range rs {
    r := rs[max-i]
    fmt.Printf("%c ", r)
}

这将输出(在Go Playground 上尝试):

r e v e t a h w   ሢ   g n i r t s   e m o s 

如果你想避免[]rune转换,你可以像这样使用utf8.DecodeLastRuneInString()

for {
    r, size := utf8.DecodeLastRuneInString(s)
    if r == utf8.RuneError {
        break
    }
    fmt.Printf("%c ", r)
    s = s[:len(s)-size]
}

这个输出一样,在Go Playground上试试这个。

【讨论】:

    【解决方案2】:

    你可以这样做:

    runes:=[]rune(str)
    for x:=len(runes)-1; x>=0; x-- {
       // work with runes[x]
    }
    

    【讨论】:

      猜你喜欢
      • 2018-06-07
      • 1970-01-01
      • 2017-06-28
      • 2017-01-28
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 2012-04-08
      相关资源
      最近更新 更多