Home > database >  Reverse range over a string
Reverse range over a string

Time:11-27

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 runes, because we can easily identify runes by high order bits of each byte or groups of bytes. From The Go Programming Language book:
enter image description here
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]
}
  • Related