英文:
Reverse range over a string
问题
如何在Go语言中“反向遍历”字符串的每个字符?
例如,给定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
,其中k
是range
指令提供的索引,原因如上所述。
更新1:
可以通过反向(从右到左)查找utf-8
的rune
来实现,因为我们可以通过每个字节或字节组的高位比特轻松识别rune
。来自《Go语言编程》一书的内容:
如图所示,我们可以从最后一个字节开始,最多需要向左扫描4个字节才能获取一个rune
。
英文:
How can I "reverse range" in Go over individual characters of a string
?
For example, given s := "some string \u1222 whatever"
- I want to do something like:
for i, v := ~reverse~ range s {
}
Please note, that I'm interested in a solution via standard library without having to write a function myself. I'm aware of tons of existing libraries which can do that, but that's irrelevant. Moreover - I can't use len(s)
and do:
for i := len(s) - 1; i >= 0; i-- {
}
since in Go built-in len
function returns only number of bytes in a string (won't work for non-ASCII strings). I also can't do len(s) - k - 1
where k
is an index provided by range
instruction due to aforementioned reason.
UPD1:
It is possible to do a reverse (right to left) lookup of utf-8
rune
s, because we can easily identify rune
s by high order bits of each byte or groups of bytes. From The Go Programming Language
book:
As you can see, we can start from the last byte and we will need to scan to the left at most 4 bytes to get a rune
.
答案1
得分: 4
最简单的解决方案是将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上尝试。
英文:
The easiest solution would be to convert the string
to []rune
, so you can iterate over it, but index "backward" (or use a downward loop):
rs := []rune(s)
max := len(rs) - 1
for i := range rs {
r := rs[max-i]
fmt.Printf("%c ", r)
}
This will output (try it on the Go Playground):
r e v e t a h w ሢ g n i r t s e m o s
If you want to avoid the []rune
conversion, you may use utf8.DecodeLastRuneInString()
like this:
for {
r, size := utf8.DecodeLastRuneInString(s)
if r == utf8.RuneError {
break
}
fmt.Printf("%c ", r)
s = s[:len(s)-size]
}
This outputs the same, try this one on the Go Playground.
答案2
得分: 1
你可以这样做:
runes := []rune(str)
for x := len(runes) - 1; x >= 0; x-- {
// 使用 runes[x] 进行操作
}
英文:
You can do:
runes:=[]rune(str)
for x:=len(runes)-1; x>=0; x-- {
// work with runes[x]
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论