¿Cómo invertir una cuerda en Go?


103

¿Cómo podemos invertir una cadena simple en Go?


1
Por lo que tengo entendido, las soluciones que se dan a continuación no funcionan con caracteres precompuestos o combinados, como dar en a+´lugar de á. Me pregunto cómo se podría tener eso en cuenta, sin normalizarlo.
siritinga

Si está confundido con una gran cantidad de respuestas similares, consulte mi punto de referencia .
Salvador Dali

Respuestas:


94

En Go1, la runa es un tipo incorporado.

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)
}

4
no puede usar len () en Go para averiguar la longitud de una cadena / Array / Slice, etc. ¿Por qué? - len () en Go significa el tamaño de la entrada en bytes. No corresponde a su longitud. - No todas las runas de utf8 son del mismo tamaño. Puede ser 1, 2, 4 u 8. - Debe usar el método del paquete unicode / ut8 RuneCountInString para obtener la longitud de la runa.
Anvesh Checka

15
@AnveshChecka, eso es incorrecto. Consulte golang.org/pkg/builtin/#len - len () en un segmento definitivamente devuelve el número de elementos, no el tamaño en bytes. Un trozo de runas es la forma correcta de hacerlo.
chowey

3
@ рытфолд Esto no funciona con la combinación de caracteres. Consulte play.golang.org/p/sBgZAV7gCb , el carácter de combinación no se intercambia con su base.
chowey

53

Russ Cox, en la lista de correo de golang-nuts , sugiere

package main 
import "fmt"
func main() { 
        input := "The quick brown 狐 jumped over the lazy 犬" 
        // Get Unicode code points. 
        n := 0
        rune := make([]rune, len(input))
        for _, r := range input { 
                rune[n] = r
                n++
        } 
        rune = rune[0:n]
        // Reverse 
        for i := 0; i < n/2; i++ { 
                rune[i], rune[n-1-i] = rune[n-1-i], rune[i] 
        } 
        // Convert back to UTF-8. 
        output := string(rune)
        fmt.Println(output)
}

20
Me gusta cómo te obligan a pensar en codificaciones.
György Andrasek

10
fuera del tema: ¿por qué es [golang-nuts] y no [go-nuts]?
Jimmy

2
Vaya, ¿qué pasa con la doble asignación al dar marcha atrás? Interesante. Ahora, piense en una cuerda con un número impar de runas. El del medio recibe un tratamiento especial, con el resultado final correcto después de todo. :) Una pequeña optimización interesante en la que no habría pensado de inmediato.
Kissaki

4
No entiendo por qué esta conversión a runa, ¿por qué no rune:=[]rune(input)?
siritinga

1
No necesitas el primero para el bucle de rango. salida: = [] runa (entrada); n: = len (salida) Y no necesitas la runa = runa [0: n]
dvallejo

29

Esto funciona, sin todos los problemas con las funciones:

func Reverse(s string) (result string) {
  for _,v := range s {
    result = string(v) + result
  }
  return 
}

6
Si bien funciona, dado que las cadenas son inmutables, es muy ineficiente. Publiqué una solución más eficiente.
peterSO

5
Esto es mucho demasiado fácil de entender. Hágalo más difícil :-) (y, "más uno" por seguir adelante)
Roboprog

2
Esta es la mejor respuesta a menos que invertir cadenas sea su cuello de botella.
Banjocat

1
@dolmen: ¿por qué esto no manejaría la combinación de personajes? un rango en una cadena devuelve una runa que es un punto de código.
Stan R.

1
@StanR. Una runa no es un glifo. Un glifo puede estar formado por múltiples puntos de código / runas. Consulte reedbeta.com/blog/programmers-intro-to-unicode/#combining-marks Los puntos de código inversos adjuntarán marcas de combinación a un punto de código base diferente.
Dolmen

14

Esto funciona en cadenas Unicode considerando 2 cosas:

  • el rango funciona en una cadena enumerando caracteres Unicode
  • La cadena se puede construir a partir de segmentos int donde cada elemento es un carácter Unicode.

Así que aquí va:

func reverse(s string) string {
    o := make([]int, utf8.RuneCountInString(s));
    i := len(o);
    for _, c := range s {
        i--;
        o[i] = c;
    }
    return string(o);
}

Asignaría i:=len(o)-1y luego doblaría el for en una sola línea for _, c:=range s { o[i--]=c; }. Hombre, ODIO el por sin paréntesis - ¿está permitido?for(_, c:=range s) { o[i--]=c; }
Lawrence Dol

¿Podrías explicar qué hace _?
Lawrence Dol

6
@Software_Monkey: o [i--] = c no está permitido en Go. - y ++ son declaraciones, no expresiones. _ significa descartar (ignorar) esa variable.
Randy Sugianto 'Yuku'

1
con go 1.1+ devuelve un error en la línea de cadena ([] int), si en su lugar se usa el tipo de runa [] para o, todo funciona
Otuk

1
@yuku: Aún falla en s: = "Les Mise \ u0301rables"
Stefan Steiger

13

De proyectos de ejemplo de Go: golang / example / stringutil / reverse.go , por Andrew Gerrand

/*
Copyright 2014 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
     http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Reverse returns its argument string reversed rune-wise left to right.
func Reverse(s string) string {
    r := []rune(s)
    for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
        r[i], r[j] = r[j], r[i]
    }
    return string(r)
}

Go Playground para revertir una cuerda

Después de invertir la cadena "bròwn", el resultado correcto debería ser "nwòrb", no "nẁorb".
Tenga en cuenta la tumba sobre la letra o.


Para conservar caracteres de combinación Unicode como "as⃝df̅" con el resultado inverso "f̅ds⃝a",
consulte otro código que se enumera a continuación:

http://rosettacode.org/wiki/Reverse_a_string#Go


2
Gracias por aclarar la diferencia con stackoverflow.com/a/10030772/3093387 - parece que estas dos soluciones difieren en cómo manejan cadenas como "bròwn".
josliber

Gracias por mencionar la solución Rosettacode que maneja la combinación de caracteres
dolmen

11

Noté esta pregunta cuando Simon publicó su solución que, dado que las cadenas son inmutables, es muy ineficiente. Las otras soluciones propuestas también son defectuosas; no funcionan o son ineficientes.

Esta es una solución eficiente que funciona, excepto cuando la cadena no es UTF-8 válida o la cadena contiene caracteres combinados.

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 犬")))
}

1
return string (runas) Funciona también.

3
@Tommy: No, return string(runes)no funciona en todos los casos.
peterSO

¿Podría explicar un poco más por qué es así? Hice un programa corto y funciona ahí, pero ¿quizás esos casos de los que hablas no se activan ahí? play.golang.org/p/yk1sAwFjol

1
@Tommy: Su programa corto simplemente demuestra que el carácter NUL es un NOP cuando se envía a una impresora o terminal. Su función Reverse2 falla para cadenas codificadas no ASCII UTF-8. Revisé su programa corto para que sea una prueba válida: play.golang.org/p/Ic5G5QEO93
peterSO

Otra "solución" incorrecta que no maneja la combinación de caracteres correctamente.
dolmen

9

Aquí hay demasiadas respuestas. Algunos de ellos son claros duplicados. Pero incluso desde la izquierda, es difícil seleccionar la mejor solución.

Así que revisé las respuestas, tiré la que no funciona para Unicode y también eliminé los duplicados. Evalué a los supervivientes para encontrar el más rápido. Entonces, aquí están los resultados con atribución (si nota las respuestas que me perdí, pero que vale la pena agregar, no dude en modificar el punto de referencia):

Benchmark_rmuller-4   100000         19246 ns/op
Benchmark_peterSO-4    50000         28068 ns/op
Benchmark_russ-4       50000         30007 ns/op
Benchmark_ivan-4       50000         33694 ns/op
Benchmark_yazu-4       50000         33372 ns/op
Benchmark_yuku-4       50000         37556 ns/op
Benchmark_simon-4       3000        426201 ns/op

Así que aquí está el método más rápido de rmuller :

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)
}

Por alguna razón, no puedo agregar un punto de referencia, por lo que puede copiarlo PlayGround(no puede ejecutar pruebas allí). Cambiar el nombre y ejecutargo test -bench=.


Ninguna de esas "soluciones" maneja la combinación de marcas correctamente.
Dolmen

6

Escribí la siguiente Reversefunción que respeta la codificación UTF8 y los caracteres combinados:

// Reverse reverses the input while respecting UTF8 encoding and combined characters
func Reverse(text string) string {
    textRunes := []rune(text)
    textRunesLength := len(textRunes)
    if textRunesLength <= 1 {
        return text
    }

    i, j := 0, 0
    for i < textRunesLength && j < textRunesLength {
        j = i + 1
        for j < textRunesLength && isMark(textRunes[j]) {
            j++
        }

        if isMark(textRunes[j-1]) {
            // Reverses Combined Characters
            reverse(textRunes[i:j], j-i)
        } 

        i = j
    }

    // Reverses the entire array
    reverse(textRunes, textRunesLength)

    return string(textRunes)
}

func reverse(runes []rune, length int) {
    for i, j := 0, length-1; i < length/2; i, j = i+1, j-1 {
        runes[i], runes[j] = runes[j], runes[i]
    }
}

// isMark determines whether the rune is a marker
func isMark(r rune) bool {
    return unicode.Is(unicode.Mn, r) || unicode.Is(unicode.Me, r) || unicode.Is(unicode.Mc, r)
}

Hice todo lo posible para que fuera lo más eficiente y legible posible. La idea es simple, atraviesa las runas en busca de personajes combinados y luego invierte las runas de los personajes combinados en su lugar. Una vez que los hayamos cubierto todos, invierta las runas de toda la cuerda también en su lugar.

Digamos que nos gustaría invertir esta cadena bròwn. El òestá representado por dos runas, una para el oy otra para este unicode \u0301aque representa la "tumba".

Para simplificar, representemos la cadena de esta manera bro'wn. Lo primero que hacemos es buscar caracteres combinados y revertirlos. Entonces ahora tenemos la cadena br'own. Finalmente, invertimos toda la cadena y terminamos con nwo'rb. Esto se nos devuelve comonwòrb

Puede encontrarlo aquí https://github.com/shomali11/util si desea utilizarlo.

A continuación, se muestran algunos casos de prueba para mostrar un par de escenarios diferentes:

func TestReverse(t *testing.T) {
    assert.Equal(t, Reverse(""), "")
    assert.Equal(t, Reverse("X"), "X")
    assert.Equal(t, Reverse("b\u0301"), "b\u0301")
    assert.Equal(t, Reverse("😎⚽"), "⚽😎")
    assert.Equal(t, Reverse("Les Mise\u0301rables"), "selbare\u0301siM seL")
    assert.Equal(t, Reverse("ab\u0301cde"), "edcb\u0301a")
    assert.Equal(t, Reverse("This `\xc5` is an invalid UTF8 character"), "retcarahc 8FTU dilavni na si `�` sihT")
    assert.Equal(t, Reverse("The quick bròwn 狐 jumped over the lazy 犬"), "犬 yzal eht revo depmuj 狐 nwòrb kciuq ehT")
}

3

Se basa en la sugerencia original de Stephan202 y parece funcionar para cadenas Unicode:

import "strings";

func Reverse( orig string ) string {
    var c []string = strings.Split( orig, "", 0 );

    for i, j := 0, len(c)-1; i < j; i, j = i+1, j-1 {
        c[i], c[j] = c[j], c[i]
    }

    return strings.Join( c, "" );
}

Alternativo, sin usar el paquete de cadenas, pero no 'seguro para Unicode':

func Reverse( s string ) string {
    b := make([]byte, len(s));
    var j int = len(s) - 1;
    for i := 0; i <= j; i++ {
        b[j-i] = s[i]
    }

    return string ( b );
}

+1. Eso funciona. Pero debo decir que es bastante extraño (por ahora) que dividir y unir sea necesario para una tarea tan simple ...
Stephan202

@martin: perdón por esa edición. Accidentalmente pegué mi respuesta actualizada en su pregunta ... me avergüenza mucho .
Stephan202

@ Stephan, no hay problema. Agregué una solución alternativa, basada en la función Bytes del paquete de cadenas.
Martin Clayton

@Nosradena: retrocedí en el mismo minuto (me sorprendió ver que Martin actualizó su respuesta con exactamente el mismo texto que acababa de escribir ... y luego me
di

@martin: la segunda versión se ve mejor si me preguntas :)
Stephan202

3
//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

Usar strings.Builder es aproximadamente 3 veces más rápido que usar la concatenación de cadenas


1
Me pregunto por qué esta pregunta no tiene votos a favor a pesar de ser la respuesta más precisa
Nilesh

3

Aquí es bastante diferente, diría que un enfoque más funcional, que no figura entre otras respuestas:

func reverse(s string) (ret string) {
    for _, v := range s {
        defer func(r rune) { ret += string(r) }(v)
    }
    return
}

Estoy bastante seguro de que no es la solución más rápida, pero muestra cómo la variable de retorno retse mantiene cerrada para su procesamiento posterior, por cada función de aplazamiento.
Vladimir Bauer

Lento y no maneja la combinación de personajes correctamente.
dolmen

1
No estoy seguro de qué tan rápido es eso, pero es hermoso.
donatJ

El rendimiento de este se puede mejorar en Go 1.14. Al menos las notas de la versión afirman tener cero gastos generales de aplazamiento.
Vladimir Bauer

2

Esta es la implementación más rápida

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)
    }
}

¿Evaluó las soluciones antes de afirmar que es la implementación más rápida?
Denys Séguret

Sí, lo hice, es por eso que el código BenchmarkReverse está presente :). Sin embargo, ya no tengo los resultados.
rmuller

Solución rápida, pero aún incorrecta, ya que no maneja la combinación de caracteres correctamente.
dolmen

¿Es cierto que @dolmen dice que esto no maneja la combinación de caracteres? ¿Hay alguna solución aquí que lo haga?
geraldss

2

Este código conserva intactas las secuencias de combinación de caracteres y también debería funcionar con entradas UTF-8 no válidas.

package stringutil
import "code.google.com/p/go.text/unicode/norm"

func Reverse(s string) string {
    bound := make([]int, 0, len(s) + 1)

    var iter norm.Iter
    iter.InitString(norm.NFD, s)
    bound = append(bound, 0)
    for !iter.Done() {
        iter.Next()
        bound = append(bound, iter.Pos())
    }
    bound = append(bound, len(s))
    out := make([]byte, 0, len(s))
    for i := len(bound) - 2; i >= 0; i-- {
        out = append(out, s[bound[i]:bound[i+1]]...)
    }
    return string(out)
}

Podría ser un poco más eficiente si las primitivas unicode / norm permitieran iterar a través de los límites de una cadena sin asignar. Consulte también https://code.google.com/p/go/issues/detail?id=9055 .


No existe tal "entrada UTF-8 no válida" en los valores de cadena: al convertir de []bytea stringGo, se reemplaza la "entrada UTF-8 no válida" por un punto de código válido \uFFFD.
dolmen

No entiendo el comentario anterior. ¿Está diciendo que el comportamiento de este código es incorrecto cuando se presenta con una cadena que contiene UTF-8 no válido?
rog

No. Estoy diciendo que UTF-8 inválido en un Go stringno existe. Pero puede existir en a []byte.
dolmen

Una cadena Go puede contener exactamente tanto utf-8 no válido como un byte []. Por ejemplo: play.golang.org/p/PG0I4FJfEN
rog

2

Si necesita manejar grupos de grafemas, use el módulo unicode o regexp.

package main

import (
  "unicode"
  "regexp"
)

func main() {
    str := "\u0308" + "a\u0308" + "o\u0308" + "u\u0308"
    println("u\u0308" + "o\u0308" + "a\u0308" + "\u0308" == ReverseGrapheme(str))
    println("u\u0308" + "o\u0308" + "a\u0308" + "\u0308" == ReverseGrapheme2(str))
}

func ReverseGrapheme(str string) string {

  buf := []rune("")
  checked := false
  index := 0
  ret := "" 

    for _, c := range str {

        if !unicode.Is(unicode.M, c) {

            if len(buf) > 0 {
                ret = string(buf) + ret
            }

            buf = buf[:0]
            buf = append(buf, c)

            if checked == false {
                checked = true
            }

        } else if checked == false {
            ret = string(append([]rune(""), c)) + ret
        } else {
            buf = append(buf, c)
        }

        index += 1
    }

    return string(buf) + ret
}

func ReverseGrapheme2(str string) string {
    re := regexp.MustCompile("\\PM\\pM*|.")
    slice := re.FindAllString(str, -1)
    length := len(slice)
    ret := ""

    for i := 0; i < length; i += 1 {
        ret += slice[length-1-i]
    }

    return ret
}

Me gustaría darte 1000 votos a favor. Todas las demás implementaciones de esta página invierten una STRING de forma incorrecta (una STRING NO es una secuencia de caracteres).
Stefan Steiger

Esto no funciona. Si invierte dos veces la cadena, no obtiene la cadena original. La diéresis combinada inicial (\ u0308), utilizada en este ejemplo, se combina con los caracteres precedentes creando una diéresis doble 'a' cuando se invierte. Si strse cotiza la salida, modifica la cotización inicial.
Joshua Kolden

2

También puede importar una implementación existente:

import "4d63.com/strrev"

Luego:

strrev.Reverse("abåd") // returns "dåba"

O para invertir una cadena que incluya caracteres de combinación Unicode:

strrev.ReverseCombining("abc\u0301\u031dd") // returns "d\u0301\u031dcba"

Estas implementaciones admiten el orden correcto de unicode multibyte y la combinación de caracteres cuando se invierte.

Nota: Las funciones de inversión de cadena incorporadas en muchos lenguajes de programación no conservan la combinación, y la identificación de caracteres combinados requiere mucho más tiempo de ejecución.


1

Seguramente no es la solución más eficiente en memoria, pero para una solución segura UTF-8 "simple", lo siguiente hará el trabajo y no romperá las runas.

En mi opinión, es el más legible y comprensible de la página.

func reverseStr(str string) (out string) {
    for _, s := range str {
        out = string(s) + out
    }

    return
}

1

Los siguientes dos métodos se ejecutan más rápido que la solución más rápida que conserva la combinación de caracteres , aunque eso no quiere decir que me esté perdiendo algo en mi configuración de referencia.

//input string s
bs := []byte(s)
var rs string
for len(bs) > 0 {
    r, size := utf8.DecodeLastRune(bs)
    rs += fmt.Sprintf("%c", r)
    bs = bs[:len(bs)-size]
} // rs has reversed string

Segundo método inspirado en este

//input string s
bs := []byte(s)
cs := make([]byte, len(bs))
b1 := 0
for len(bs) > 0 {
    r, size := utf8.DecodeLastRune(bs)
    d := make([]byte, size)
    _ = utf8.EncodeRune(d, r)
    b1 += copy(cs[b1:], d)
    bs = bs[:len(bs) - size]
} // cs has reversed bytes

Esto es lo que falta en su punto de referencia: su solución es más rápida porque no conserva la combinación de caracteres. Es injusto compararlos.
dolmen

1

NOTA: Esta respuesta es de 2009, por lo que probablemente ya existen mejores soluciones.


Parece un poco "indirecto" y probablemente no muy eficiente, pero ilustra cómo se puede usar la interfaz de Reader para leer cadenas. Los IntVectors también parecen muy adecuados como búfer cuando se trabaja con cadenas utf8.

Sería aún más corto si se omite la parte de 'tamaño' y la inserción en el vector mediante Insertar, pero supongo que sería menos eficiente, ya que todo el vector debe retroceder uno cada vez que se agrega una nueva runa. .

Esta solución definitivamente funciona con caracteres utf8.

package main

import "container/vector";
import "fmt";
import "utf8";
import "bytes";
import "bufio";


func
main() {
    toReverse := "Smørrebrød";
    fmt.Println(toReverse);
    fmt.Println(reverse(toReverse));
}

func
reverse(str string) string {
    size := utf8.RuneCountInString(str);
    output := vector.NewIntVector(size);
    input := bufio.NewReader(bytes.NewBufferString(str));
    for i := 1; i <= size; i++ {
        rune, _, _ := input.ReadRune();
        output.Set(size - i, rune);
    }
    return string(output.Data());
}

¿Por qué agrega todos esos puntos y comas finales?
Morteza R

@ olivier-mason Es hora de aprender sobre gofmt al compartir código Go.
Dolmen

1
Esa respuesta fue de hace ocho años.
Oliver Mason

@OliverMason Nunca es demasiado tarde para arreglar (o eliminar) una solución imperfecta.
dolmen

0

Una versión que creo que funciona en Unicode. Se basa en las funciones utf8.Rune:

func Reverse(s string) string {
    b := make([]byte, len(s));
    for i, j := len(s)-1, 0; i >= 0; i-- {
        if utf8.RuneStart(s[i]) {
            rune, size := utf8.DecodeRuneInString(s[i:len(s)]);
            utf8.EncodeRune(rune, b[j:j+size]);
            j += size;
        }
    }
    return string(b);
}

0

runa es un tipo, así que úsala. Además, Go no usa punto y coma.

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))
}

Usó punto y coma cuando se publicó esa pregunta.
OneOfOne

Otra "solución" incorrecta que no maneja la combinación de caracteres correctamente.
dolmen


0

Para cadenas simples, es posible utilizar dicha construcción:

func Reverse(str string) string {
    if str != "" {
        return Reverse(str[1:]) + str[:1]
    }
    return ""   
}

-1

Aquí hay otra solución:

func ReverseStr(s string) string {
    chars := []rune(s)
    rev := make([]rune, 0, len(chars))
    for i := len(chars) - 1; i >= 0; i-- {
        rev = append(rev, chars[i])
    }
    return string(rev)
}

Sin embargo, la solución de yazu anterior es más elegante ya que invierte el []runecorte en su lugar.


-1

Otra solución más (tm):

package main 
import "fmt"

type Runes []rune

func (s Runes) Reverse() (cp Runes) {
    l := len(s); cp = make(Runes, l)
    // i <= 1/2 otherwise it will mess up with odd length strings
    for i := 0; i <= l/2; i++ { 
        cp[i], cp[l-1-i] = s[l-1-i], s[i] 
    }
    return cp
}

func (s Runes) String() string {
    return string(s)
}

func main() { 
    input := "The quick brown 狐 jumped over the lazy 犬 +odd" 
    r := Runes(input)
    output := r.Reverse()
    valid := string(output.Reverse()) == input
    fmt.Println(len(r), len(output), r, output.Reverse(), valid)
}

-1
package reverseString

import "strings"

// ReverseString - output the reverse string of a given string s
func ReverseString(s string) string {

    strLen := len(s)

    // The reverse of a empty string is a empty string
    if strLen == 0 {
        return s
    }

    // Same above
    if strLen == 1 {
        return s
    }

    // Convert s into unicode points
    r := []rune(s)

    // Last index
    rLen := len(r) - 1

    // String new home
    rev := []string{}

    for i := rLen; i >= 0; i-- {
        rev = append(rev, string(r[i]))
    }

    return strings.Join(rev, "")
}

Prueba

package reverseString

import (
    "fmt"
    "strings"
    "testing"
)

func TestReverseString(t *testing.T) {

    s := "GO je úžasné!"
    r := ReverseString(s)

    fmt.Printf("Input: %s\nOutput: %s", s, r)

    revR := ReverseString(r)

    if strings.Compare(s, revR) != 0 {
        t.Errorf("Expecting: %s\n. Got: %s\n", s, revR)
    }
}

Salida

Input: GO je úžasné!
Output: nsažú ej OG
PASS
ok      github.com/alesr/reverse-string 0.098s

Esto funciona si la entrada está en NFC. Pero como la mayoría de las otras soluciones incorrectas aquí, no funciona con la combinación de personajes.
dolmen

-1
    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
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.