122 votes

Comment inverser une chaîne de caractères en Go ?

Comment inverser une simple chaîne de caractères en Go ? Il semble qu'il n'existe pas de fonction "reverse" de type Perl.

1 votes

D'après ce que je comprends, les solutions données ci-dessous ne fonctionnent pas avec les caractères précomposés ou combinés, comme le fait de donner a+´ au lieu de á . Je me demande comment on pourrait en tenir compte, sans le normaliser.

0 votes

Si vous n'arrivez pas à vous y retrouver dans un grand nombre de réponses similaires, vérifiez mon point de référence .

2 votes

Pour les chaînes de caractères qui sont pas simple, voir stackoverflow.com/a/62743214/6309

126voto

yazu Points 1976

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

4 votes

Vous ne pouvez pas utiliser len() en Go pour connaître la longueur d'une chaîne de caractères, d'un tableau, d'une tranche, etc... Voici pourquoi ? - len() en Go signifie la taille de l'entrée en octets. Elle ne correspond pas à sa longueur. - Toutes les runes d'utf8 n'ont pas la même taille. Elles peuvent être soit 1, 2, 4, ou 8. - Vous devez utiliser la méthode RuneCountInString du paquet unicode/ut8 pour obtenir la longueur de la rune.

25 votes

@AnveshChecka, c'est incorrect. Voir golang.org/pkg/builtin/#len - len() sur une tranche renvoie définitivement le nombre d'éléments, et non la taille en octets. Une tranche de runes est la manière correcte de le faire.

7 votes

@ Cela ne fonctionne pas avec les caractères de combinaison. Voir play.golang.org/p/sBgZAV7gCb le caractère de combinaison n'est pas échangé avec sa base.

59voto

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

23 votes

J'aime la façon dont ils vous obligent à penser aux encodages.

15 votes

Hors sujet : pourquoi c'est [golang-nuts] et pas [go-nuts] ?

2 votes

Wow, qu'est-ce qui se passe avec la double affectation en marche arrière ? Intéressant. Maintenant, pensez à une chaîne avec un nombre impair de runes. La rune du milieu bénéficie d'un traitement spécial, avec un résultat final correct après tout :) Une petite optimisation intéressante à laquelle je n'aurais pas pensé tout de suite.

40voto

Simon Points 31

Cela fonctionne, sans tout le bricolage des fonctions :

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

9 votes

Bien que cela fonctionne, puisque les chaînes de caractères sont immuables, c'est très inefficace. J'ai posté une solution plus efficace.

6 votes

C'est beaucoup trop facile à comprendre. Rendez-le plus difficile :-) (et, "plus un" pour s'y mettre)

2 votes

C'est la meilleure réponse, sauf si l'inversion des cordes est votre goulot d'étranglement.

15voto

yuku Points 15705

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

  • gamme travaille sur une chaîne de caractères en énumérant les caractères unicode
  • La chaîne peut être construite à partir de tranches d'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);
}

0 votes

J'assignerais i:=len(o)-1 et ensuite plier les pour en une seule ligne for _, c:=range s { o[i--]=c; } . Je déteste le pour sans parenthèses - est-ce autorisé ? for(_, c:=range s) { o[i--]=c; }

0 votes

Pouvez-vous expliquer ce que fait le _ ?

7 votes

@Software_Monkey : o[i--] = c n'est pas autorisé en Go. -- et ++ sont des déclarations, pas des expressions. _ signifie qu'il faut rejeter (ignorer) cette variable.

14voto

peterSO Points 25725

J'ai remarqué cette question lorsque Simon posté sa solution ce qui, puisque les chaînes de caractères sont immuables, est très inefficace. Les autres solutions proposées sont également défectueuses ; elles ne fonctionnent pas ou sont inefficaces.

Voici une solution efficace qui fonctionne, sauf lorsque la chaîne n'est pas un UTF-8 valide 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 犬")))
}

1 votes

Return string(runes) Fonctionne aussi bien.

3 votes

@Tommy : Non, return string(runes) ne fonctionne pas dans tous les cas.

0 votes

Pourriez-vous m'expliquer un peu plus pourquoi ? J'ai fait un petit programme et cela fonctionne, mais peut-être que les cas dont vous parlez ne sont pas déclenchés ici ? play.golang.org/p/yk1sAwFjol

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X