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
.
CodePudding user response:
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.
CodePudding user response:
You can do:
runes:=[]rune(str)
for x:=len(runes)-1; x>=0; x-- {
// work with runes[x]
}