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
}
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:
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))
}
prueba el siguiente código:
package main
import "fmt"
func reverse(s string) string {
chars := []rune(s)
for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 {
chars[i], chars[j] = chars[j], chars[i]
}
return string(chars)
}
func main() {
fmt.Printf("%v/n", reverse("abcdefg"))
}
para obtener más información, consulte http://golangcookbook.com/chapters/strings/reverse/
y http://www.dotnetperls.com/reverse-string-go
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