How can we reverse a simple string in Go?
In Go1 rune is a builtin type.
func Reverse(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
This works, without all the mucking about with functions:
func Reverse(s string) (result string) {
for _,v := range s {
result = string(v) + result
}
return
}
I noticed this question when Simon posted his solution which, since strings are immutable, is very inefficient. The other proposed solutions are also flawed; they don't work or they are inefficient.
Here's an efficient solution that works, except when the string is not valid UTF-8 or the string contains combining characters.
package main
import "fmt"
func Reverse(s string) string {
n := len(s)
runes := make([]rune, n)
for _, rune := range s {
n--
runes[n] = rune
}
return string(runes[n:])
}
func main() {
fmt.Println(Reverse(Reverse("Hello, 世界")))
fmt.Println(Reverse(Reverse("The quick brown 狐 jumped over the lazy 犬")))
}
//Reverse reverses string using strings.Builder. It's about 3 times faster
//than the one with using a string concatenation
func Reverse(in string) string {
var sb strings.Builder
runes := []rune(in)
for i := len(runes) - 1; 0 <= i; i-- {
sb.WriteRune(runes[i])
}
return sb.String()
}
//Reverse reverses string using string
func Reverse(in string) (out string) {
for _, r := range in {
out = string(r) + out
}
return
}
BenchmarkReverseStringConcatenation-8 1000000 1571 ns/op 176 B/op 29 allocs/op
BenchmarkReverseStringsBuilder-8 3000000 499 ns/op 56 B/op 6 allocs/op
Using strings.Builder is about 3 times faster than using string concatenation
This is the fastest implementation
func Reverse(s string) string {
size := len(s)
buf := make([]byte, size)
for start := 0; start < size; {
r, n := utf8.DecodeRuneInString(s[start:])
start += n
utf8.EncodeRune(buf[size-start:], r)
}
return string(buf)
}
const (
s = "The quick brown 狐 jumped over the lazy 犬"
reverse = "犬 yzal eht revo depmuj 狐 nworb kciuq ehT"
)
func TestReverse(t *testing.T) {
if Reverse(s) != reverse {
t.Error(s)
}
}
func BenchmarkReverse(b *testing.B) {
for i := 0; i < b.N; i++ {
Reverse(s)
}
}
A simple stroke with rune:
func ReverseString(s string) string {
runes := []rune(s)
size := len(runes)
for i := 0; i < size/2; i++ {
runes[size-i-1], runes[i] = runes[i], runes[size-i-1]
}
return string(runes)
}
func main() {
fmt.Println(ReverseString("Abcdefg 汉语 The God"))
}
: doG ehT 语汉 gfedcbA
You could also import an existing implementation:
import "4d63.com/strrev"
Then:
strrev.Reverse("abåd") // returns "dåba"
Or to reverse a string including unicode combining characters:
strrev.ReverseCombining("abc\u0301\u031dd") // returns "d\u0301\u031dcba"
These implementations supports correct ordering of unicode multibyte and combing characters when reversed.
Note: Built-in string reverse functions in many programming languages do not preserve combining, and identifying combining characters requires significantly more execution time.
func ReverseString(str string) string {
output :=""
for _, char := range str {
output = string(char) + output
}
return output
}
// "Luizpa" -> "apziuL"
// "123日本語" -> "語本日321"
// "⚽" -> "⚽"
// "´a´b´c´" -> "´c´b´a´"
For simple strings it possible to use such construction:
func Reverse(str string) string {
if str != "" {
return Reverse(str[1:]) + str[:1]
}
return ""
}
For Unicode strings it might look like this:
func RecursiveReverse(str string) string {
if str == "" {
return ""
}
runes := []rune(str)
return RecursiveReverse(string(runes[1:])) + string(runes[0])
}
func Reverse(s string) string {
r := []rune(s)
var output strings.Builder
for i := len(r) - 1; i >= 0; i-- {
output.WriteString(string(r[i]))
}
return output.String()
}
Simple, Sweet and Performant
func reverseStr(str string) string {
strSlice := []rune(str) //converting to slice of runes
length := len(strSlice)
for i := 0; i < (length / 2); i++ {
strSlice[i], strSlice[length-i-1] = strSlice[length-i-1], strSlice[i]
}
return string(strSlice) //converting back to string
}
Reversing a string by word is a similar process. First, we convert the string into an array of strings where each entry is a word. Next, we apply the normal reverse loop to that array. Finally, we smush the results back together into a string that we can return to the caller.
package main
import (
"fmt"
"strings"
)
func reverse_words(s string) string {
words := strings.Fields(s)
for i, j := 0, len(words)-1; i < j; i, j = i+1, j-1 {
words[i], words[j] = words[j], words[i]
}
return strings.Join(words, " ")
}
func main() {
fmt.Println(reverse_words("one two three"))
}
rune is a type, so use it. Moreover, Go doesn't use semicolons.
func reverse(s string) string {
l := len(s)
m := make([]rune, l)
for _, c := range s {
l--
m[l] = c
}
return string(m)
}
func main() {
str := "the quick brown 狐 jumped over the lazy 犬"
fmt.Printf("reverse(%s): [%s]\n", str, reverse(str))
}
func reverseString(someString string) string {
runeString := []rune(someString)
var reverseString string
for i := len(runeString)-1; i >= 0; i -- {
reverseString += string(runeString[i])
}
return reverseString
}
Strings are immutable object in golang, unlike C inplace reverse is not possible with golang. With C , you can do something like,
void reverseString(char *str) {
int length = strlen(str)
for(int i = 0, j = length-1; i < length/2; i++, j--)
{
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
}
But with golang, following one, uses byte to convert the input into bytes first and then reverses the byte array once it is reversed, convert back to string before returning. works only with non unicode type string.
package main
import "fmt"
func main() {
s := "test123 4"
fmt.Println(reverseString(s))
}
func reverseString(s string) string {
a := []byte(s)
for i, j := 0, len(s)-1; i < j; i++ {
a[i], a[j] = a[j], a[i]
j--
}
return string(a)
}
func reverseStr(b string) {
for _, v := range []rune(b) {
defer fmt.Printf("%c", v)
}
}
Defer is useful for this as it is LIFO - Last in First Out
Another hack is to use built-in language features, for example, defer:
package main
import "fmt"
func main() {
var name string
fmt.Scanln(&name)
for _, char := range []rune(name) {
defer fmt.Printf("%c", char) // <-- LIFO does it all for you
}
}