Comment inverser une chaîne dans Go?

103

Comment inverser une simple chaîne dans Go?

user211499
la source
1
Pour autant que je sache, les solutions données ci-dessous ne fonctionnent pas avec des caractères précomposés ou combinés, comme donner a+´au lieu de á. Je me demande comment cela pourrait être pris en compte, sans le normaliser.
siritinga
Si vous êtes confus avec un grand nombre de réponses similaires, vérifiez mon point de repère .
Salvador Dali

Réponses:

94

Dans Go1, la rune est un type intégré.

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)
}
yazu
la source
4
vous ne pouvez pas utiliser len () dans Go pour connaître la longueur d'une chaîne / Array / Slice etc ... Voici pourquoi? - len () dans Go signifie la taille de l'entrée en octets. Il ne correspond pas à sa longueur. - Toutes les runes d'utf8 ne sont pas de la même taille. Il peut être 1, 2, 4 ou 8. - Vous devez utiliser la méthode RuneCountInString du package unicode / ut8 pour obtenir la longueur de la rune.
Anvesh Checka
15
@AnveshChecka, c'est incorrect. Voir golang.org/pkg/builtin/#len - len () sur une tranche renvoie définitivement le nombre d'éléments, pas la taille en octets. Une tranche de runes est la bonne façon de le faire.
chowey
3
@ рытфолд Cela ne fonctionne pas avec la combinaison de caractères. Voir play.golang.org/p/sBgZAV7gCb , le caractère de combinaison n'est pas échangé avec sa base.
chowey
53

Russ Cox, sur la liste de diffusion Golang-Nuts , suggère

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)
}
user181548
la source
20
J'aime la façon dont ils vous obligent à penser aux encodages.
György Andrasek
10
hors sujet: pourquoi est-ce [golang-nut] et pas [go-nut]?
Jimmy
2
Wow, wtf est en place avec la double affectation lors de l'inversion? Intéressant. Maintenant, pensez à une chaîne avec un nombre impair de runes. Celui du milieu reçoit un traitement spécial, avec le résultat final correct après tout. :) Une petite optimisation intéressante à laquelle je n'aurais pas pensé tout de suite.
Kissaki
4
Je ne comprends pas pourquoi cette conversion en runes, pourquoi pas rune:=[]rune(input)?
siritinga
1
Vous n'avez pas besoin du premier pour la boucle de plage. sortie: = [] rune (entrée); n: = len (sortie) Et vous n'avez pas besoin de la rune = rune [0: n]
dvallejo
29

Cela fonctionne, sans tous les soucis avec les fonctions:

func Reverse(s string) (result string) {
  for _,v := range s {
    result = string(v) + result
  }
  return 
}
Simon
la source
6
Bien que cela fonctionne, puisque les chaînes sont immuables, c'est très inefficace. J'ai publié une solution plus efficace.
peterSO
5
C'est beaucoup trop facile à comprendre. Rendez-le plus difficile :-) (et, "plus un" pour juste
continuer
2
C'est la meilleure réponse à moins que l'inversion des chaînes ne soit votre goulot d'étranglement.
Banjocat
1
@dolmen - pourquoi cela ne gérerait-il pas la combinaison de caractères? une plage sur une chaîne renvoie une rune qui est un point de code.
Stan R.
1
@StanR. Une rune n'est pas un glyphe. Un glyphe peut être composé de plusieurs points de code / runes. Voir reedbeta.com/blog/programmers-intro-to-unicode/#combining-marks L' inversion des points de code attachera des marques de combinaison à un point de code de base différent.
dolmen
14

Cela fonctionne sur les chaînes Unicode en considérant 2 choses:

  • range fonctionne sur la chaîne en énumérant les caractères unicode
  • string peut être construit à partir de tranches int où chaque élément est un caractère unicode.

Alors voilà:

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);
}
Randy Sugianto 'Yuku'
la source
Je attribuerais i:=len(o)-1puis plierais le pour en une seule ligne for _, c:=range s { o[i--]=c; }. Man I HATE the for sans parenthèses - est-ce permis:for(_, c:=range s) { o[i--]=c; }
Lawrence Dol
Pouvez-vous expliquer ce que fait le _?
Lawrence Dol
6
@Software_Monkey: o [i--] = c n'est pas autorisé dans Go. - et ++ sont des instructions, pas des expressions. _ signifie rejeter (ignorer) cette variable.
Randy Sugianto 'Yuku'
1
avec go 1.1+, il renvoie une erreur dans la ligne de chaîne ([] int), si à la place [] le type de rune est utilisé pour o, tout fonctionne
Otuk
1
@yuku: Échoue toujours sur s: = "Les Mise \ u0301rables"
Stefan Steiger
13

Des exemples de projets Go: golang / exemple / stringutil / reverse.go , par 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 pour inverser une chaîne

Après avoir inversé la chaîne "bròwn", le résultat correct devrait être "nwòrb" et non "nẁorb".
Notez la tombe au-dessus de la lettre o.


Pour préserver la combinaison de caractères Unicode tels que "as⃝df̅" avec le résultat inverse "f̅ds⃝a",
veuillez vous référer à un autre code répertorié ci-dessous:

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

Ivan Chau
la source
2
Merci d'avoir clarifié la différence avec stackoverflow.com/a/10030772/3093387 - il semble que ces deux solutions diffèrent dans la façon dont elles traitent des chaînes comme "bròwn".
josliber
Merci d'avoir mentionné la solution Rosettacode qui gère la combinaison de caractères
dolmen
11

J'ai remarqué cette question lorsque Simon a posté sa solution qui, puisque les chaînes sont immuables, est très inefficace. Les autres solutions proposées sont également imparfaites; ils ne fonctionnent pas ou ils sont inefficaces.

Voici une solution efficace qui fonctionne, sauf lorsque la chaîne n'est pas valide UTF-8 ou que la chaîne contient des caractères de combinaison.

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 犬")))
}
peterSO
la source
1
return string (runes) Fonctionne également.
3
@Tommy: Non, return string(runes)cela ne fonctionne pas dans tous les cas.
peterSO
pourriez-vous s'il vous plaît expliquer un peu plus pourquoi? J'ai fait un programme court et ça marche là-bas, mais peut-être que les cas dont vous parlez ne sont pas déclenchés là-bas? play.golang.org/p/yk1sAwFjol
1
@Tommy: Votre programme court montre simplement que le caractère NUL est un NOP lorsqu'il est envoyé à une imprimante ou à un terminal. Votre fonction Reverse2 échoue pour les chaînes codées non ASCII UTF-8. J'ai révisé votre programme court pour qu'il s'agisse d'un test valide: play.golang.org/p/Ic5G5QEO93
peterSO
Une autre "solution" erronée qui ne gère pas correctement la combinaison de caractères.
dolmen
9

Il y a trop de réponses ici. Certains d'entre eux sont clairement des doublons. Mais même à partir de celle de gauche, il est difficile de sélectionner la meilleure solution.

J'ai donc parcouru les réponses, jeté celle qui ne fonctionne pas pour unicode et également supprimé les doublons. J'ai comparé les survivants pour trouver le plus rapide. Voici donc les résultats avec attribution (si vous remarquez les réponses que j'ai manquées, mais qui valent la peine d'être ajoutées, n'hésitez pas à modifier le benchmark):

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

Voici donc la méthode la plus rapide 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)
}

Pour une raison quelconque, je ne peux pas ajouter de benchmark, vous pouvez donc le copier à partir de PlayGround(vous ne pouvez pas y exécuter de tests). Renommez-le et exécutezgo test -bench=.

Salvador Dali
la source
Aucune de ces «solutions» ne gère correctement la combinaison des marques .
dolmen
6

J'ai écrit la Reversefonction suivante qui respecte l'encodage UTF8 et les caractères combinés:

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

J'ai fait de mon mieux pour le rendre aussi efficace et lisible que possible. L'idée est simple, parcourez les runes à la recherche de caractères combinés, puis inversez les runes des personnages combinés sur place. Une fois que nous les avons tous couverts, inversez les runes de la chaîne entière également en place.

Supposons que nous souhaitons inverser cette chaîne bròwn. Le òest représenté par deux runes, une pour le oet un pour cet unicode \u0301aqui représente la «tombe».

Pour plus de simplicité, représentons la chaîne comme ceci bro'wn. La première chose que nous faisons est de rechercher des caractères combinés et de les inverser. Alors maintenant, nous avons la chaîne br'own. Enfin, nous inversons toute la chaîne et finissons par nwo'rb. Ceci nous est retourné commenwòrb

Vous pouvez le trouver ici https://github.com/shomali11/util si vous souhaitez l'utiliser.

Voici quelques cas de test pour montrer quelques scénarios différents:

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")
}
Raed Shomali
la source
3

S'appuyant sur la suggestion originale de Stephan202, et semble fonctionner pour les chaînes 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, "" );
}

Alternatif, n'utilisant pas de package de chaînes, mais pas 'unicode-safe':

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 );
}
Martin Clayton
la source
+1. Ça marche. Mais je dois dire qu'il est plutôt étrange (pour l'instant) que le fractionnement et la jonction soient nécessaires pour une tâche aussi simple ...
Stephan202
@martin: désolé pour cette modification. J'ai accidentellement collé ma réponse mise à jour dans votre question ... j'ai très honte .
Stephan202
@Stephan - pas de problème. J'ai ajouté une solution alternative, basée sur la fonction Bytes du package de chaînes.
martin clayton
@Nosradena: j'ai reculé dans la même minute (j'ai été surpris de voir que Martin a mis à jour sa réponse avec exactement le même texte que je venais d'écrire ... et puis il m'est apparu;)
Stephan202
@martin: la deuxième version est meilleure si vous me demandez :)
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

Utilisation de chaînes.Builder est environ 3 fois plus rapide que l'utilisation de la concaténation de chaînes

Vlad Bezden
la source
1
Je me demande pourquoi cette question n'a pas de vote favorable alors qu'elle est la réponse la plus précise
Nilesh
3

Voici une approche assez différente, je dirais plus fonctionnelle, non répertoriée parmi d'autres réponses:

func reverse(s string) (ret string) {
    for _, v := range s {
        defer func(r rune) { ret += string(r) }(v)
    }
    return
}
Vladimir Bauer
la source
Je suis à peu près sûr que ce n'est pas la solution la plus rapide, mais elle montre comment la variable de retour retest maintenue en fermeture pour un traitement ultérieur, par chaque fonction de report.
Vladimir Bauer le
Lent et ne gère pas correctement la combinaison de caractères.
dolmen
1
Je ne sais pas à quelle vitesse c'est, mais c'est magnifique.
donatJ
Les performances de celui-ci peuvent être améliorées dans Go 1.14. Au moins, les notes de publication prétendent n'avoir aucune surcharge de report.
Vladimir Bauer le
2

C'est la mise en œuvre la plus rapide

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)
    }
}
rmuller
la source
Avez-vous évalué les solutions avant de prétendre que c'est la mise en œuvre la plus rapide?
Denys Séguret
oui je l'ai fait, c'est pourquoi le code BenchmarkReverse est présent :). Cependant je n'ai plus les résultats.
rmuller le
Solution rapide, mais toujours erronée car elle ne gère pas correctement la combinaison de caractères.
dolmen
Est-ce vrai comme @dolmen dit que cela ne gère pas la combinaison de caractères? Y a-t-il une solution ici?
geraldss
2

Ce code préserve les séquences de combinaison de caractères intactes et devrait également fonctionner avec une entrée UTF-8 non valide.

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

Cela pourrait être un peu plus efficace si les primitives unicode / norm permettaient d'itérer à travers les limites d'une chaîne sans allouer. Voir également https://code.google.com/p/go/issues/detail?id=9055 .

rog
la source
Il n'y a pas de telle «entrée UTF-8 non valide» dans les valeurs de chaîne: lors de la conversion de []byteen stringGo, remplace «entrée UTF-8 non valide» par un point de code valide \uFFFD.
dolmen
Je ne comprends pas le commentaire ci-dessus. Êtes-vous en train de dire que le comportement de ce code est incorrect lorsqu'il est présenté avec une chaîne contenant un UTF-8 invalide?
rog
Non, je dis que l'UTF-8 invalide dans un Go stringn'existe pas. Mais il peut exister dans un fichier []byte.
dolmen
Une chaîne Go peut contenir exactement autant d'utf-8 invalide qu'un [] octet. Par exemple: play.golang.org/p/PG0I4FJfEN
rog
2

Si vous avez besoin de gérer des clusters de graphèmes, utilisez le module unicode ou 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
}
masakielastic
la source
Je voudrais vous donner 1 000 votes positifs. Toutes les autres implémentations de cette page inversent incorrectement une STRING (une STRING n'est PAS une séquence de caractères).
Stefan Steiger
Cela ne marche pas. Si vous double inversez la chaîne, vous n'obtenez pas la chaîne d'origine. Le tréma de combinaison principal (\ u0308), utilisé dans cet exemple, se combine avec les caractères précédents pour créer un double tréma «a» lorsqu'il est inversé. Si la strsortie est citée, elle modifie la citation principale!
Joshua Kolden
2

Vous pouvez également importer une implémentation existante:

import "4d63.com/strrev"

Ensuite:

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

Ou pour inverser une chaîne comprenant des caractères combinant unicode:

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

Ces implémentations prennent en charge l'ordre correct des caractères multi-octets Unicode et le peignage des caractères lorsqu'ils sont inversés.

Remarque: les fonctions d'inversion de chaîne intégrées dans de nombreux langages de programmation ne préservent pas la combinaison, et l'identification des caractères de combinaison nécessite beaucoup plus de temps d'exécution.

Leigh McCulloch
la source
1

Ce n'est certainement pas la solution la plus efficace en termes de mémoire, mais pour une solution sûre UTF-8 "simple", ce qui suit fera le travail et ne cassera pas les runes.

C'est à mon avis le plus lisible et le plus compréhensible de la page.

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

    return
}
donatJ
la source
1

Les deux méthodes suivantes fonctionnent plus rapidement que la solution la plus rapide qui préserve la combinaison de caractères , même si cela ne veut pas dire que je manque quelque chose dans ma configuration de référence.

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

Deuxième méthode inspirée de cela

//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
Sridhar
la source
Voici ce qui vous manque dans votre benchmark: votre solution est plus rapide car elle ne conserve pas la combinaison de caractères. Il est tout simplement injuste de les comparer.
dolmen
1

REMARQUE: Cette réponse date de 2009, il existe donc probablement de meilleures solutions à l'heure actuelle.


Cela semble un peu «rond-point», et probablement pas très efficace, mais illustre comment l'interface de Reader peut être utilisée pour lire des chaînes. Les IntVectors semblent également très appropriés comme tampons lorsque vous travaillez avec des chaînes utf8.

Ce serait encore plus court si vous omettiez la partie `` taille '' et l'insertion dans le vecteur par Insertion, mais je suppose que ce serait moins efficace, car le vecteur entier doit alors être repoussé de un à chaque fois qu'une nouvelle rune est ajoutée .

Cette solution fonctionne définitivement avec les caractères 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());
}
Oliver Mason
la source
Pourquoi ajoutez-vous tous ces points-virgules de fin?
Morteza R
@ olivier-mason Il est temps d'en savoir plus sur gofmt lors du partage de code Go.
dolmen
1
Cette réponse remonte à huit ans.
Oliver Mason
@OliverMason Il n'est jamais trop tard pour corriger (ou supprimer) une solution imparfaite.
dolmen
0

Une version qui, je pense, fonctionne sur unicode. Il est construit sur les fonctions 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);
}
Jonathan Wright
la source
0

la rune est un type, alors utilisez-la. De plus, Go n'utilise pas de points-virgules.

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))
}
Walter
la source
Il a utilisé des points-virgules lorsque cette question a été publiée.
OneOfOne
Une autre "solution" erronée qui ne gère pas correctement la combinaison de caractères.
dolmen
0

Pour les chaînes simples, il est possible d'utiliser une telle construction:

func Reverse(str string) string {
    if str != "" {
        return Reverse(str[1:]) + str[:1]
    }
    return ""   
}
Sergo Kurbanov
la source
-1

Voici encore une autre solution:

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

Cependant, la solution de yazu ci-dessus est plus élégante car il inverse la []runetranche en place.

Jabba
la source
-1

Encore une autre solution (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)
}
OneOfOne
la source
-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, "")
}

Tester

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

Production

Input: GO je úžasné!
Output: nsažú ej OG
PASS
ok      github.com/alesr/reverse-string 0.098s
Alessandro Resta
la source
Cela fonctionne si l'entrée est en NFC. Mais comme la plupart des autres mauvaises solutions ici, cela ne fonctionne pas avec la combinaison de caractères.
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
    }
saurabh
la source