una strrev reves recursivo punteros palabra invertir imprimir dev complemento cadenas cadena adn string go reverse

string - strrev - invertir una palabra en una cadena c++



Cómo invertir una cadena en Go? (24)

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


Aquí es bastante diferente, yo diría que es 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 }

Credits


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 anterior de yazu es más elegante ya que invierte la rebanada de []rune en su lugar.


Basándose 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, no utiliza el paquete de cadenas, pero no es ''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 ); }


De proyectos de ejemplo 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) }

Ir a la zona de juegos para invertir una cadena

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

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

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


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


Escribí la siguiente función Reverse 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 hacerlo lo más eficiente y legible posible. La idea es simple, recorrer las runas buscando caracteres combinados y luego invertir las runas de los personajes combinados en el lugar. Una vez que los hayamos cubierto todos, invierta las runas de la cadena completa también en el lugar.

Digamos que nos gustaría revertir esta cadena bròwn . El ò está representado por dos runas, una para el o y otra para este unicode /u0301a que representa la "tumba".

Para simplificar, representemos la cadena como este bro''wn . Lo primero que hacemos es buscar los caracteres combinados e invertirlos. Así que ahora tenemos la cuerda br''own . Finalmente, nwo''rb la cadena completa y terminamos con nwo''rb . Esto se nos nwòrb como nwòrb

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

Aquí hay 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") }


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


Este código preserva las secuencias de la combinación de caracteres intactos, y debería funcionar también con una entrada UTF-8 no válida.

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. Ver también https://code.google.com/p/go/issues/detail?id=9055 .


Esto funciona en cadenas de Unicode teniendo en cuenta 2 cosas:

  • rango trabaja en 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); }


Esto funciona, sin todo el problema con las funciones:

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


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

Así que revisé las respuestas, descarté la que no funciona para Unicode y también eliminé duplicados. Hice una evaluación comparativa de los supervivientes para encontrar el más rápido. Así que aquí están los resultados con atribución (si notas las respuestas que eché de menos, pero vale la pena agregarlas, puedes 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 desde PlayGround (no puede ejecutar pruebas allí). Renombrarlo y ejecutar go test -bench=.


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 falta 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 this

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


Me di cuenta de esta pregunta cuando publicó su solución que, como las cadenas son inmutables, es muy ineficiente. Las otras soluciones propuestas también son defectuosas; no funcionan o son ineficientes.

Aquí hay una solución eficiente que funciona, excepto cuando la cadena no es válida UTF-8 o la cadena contiene la combinación de caracteres.

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


Para cuerdas simples es posible usar tal construcción:

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


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

Sería aún más corto al omitir la parte de ''tamaño'', y la inserción en el vector por Insertar, pero supongo que sería menos eficiente, ya que el vector completo necesita ser retrocedido por 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()); }


Seguramente no es la solución más eficiente en cuanto a la 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 }


Si necesita manejar los conglomerados 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 }


Sin embargo, otra solución (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) }


También podría importar una implementación existente:

import "4d63.com/strrev"

Entonces:

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

O para invertir una cadena que incluye caracteres que combinan unicode:

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

Estas implementaciones admiten el orden correcto de multibyte unicode y combinan caracteres cuando se invierten.

Nota: Las funciones inversas 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.


Una versión que creo que funciona en Unicode. Está construido sobre 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); }


la runa es un tipo, entonces ú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)) }



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


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