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

5voto

martin clayton Points 41306

Basé 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, "" );
}

Autre solution, qui n'utilise pas le paquet "strings", mais qui n'est 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 );
}

0 votes

+1. Cela fonctionne. Mais je dois dire qu'il est plutôt étrange (pour l'instant) que la division et la jonction soient nécessaires pour une tâche aussi simple...

0 votes

@martin : désolé pour cette modification. J'ai accidentellement collé ma réponse mise à jour dans votre question... moi très honteux .

0 votes

@Stephan - pas de problème. J'ai ajouté une solution alternative, basée sur la fonction "strings package Bytes".

4voto

rmuller Points 792

C'est l'implémentation 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)
    }
}

0 votes

Avez-vous évalué les solutions avant de prétendre qu'il s'agit de la mise en œuvre la plus rapide ?

0 votes

Oui je l'ai fait, c'est pourquoi le code BenchmarkReverse est présent :) . Cependant, je n'ai plus les résultats.

3 votes

Solution rapide, mais toujours erronée car elle ne gère pas correctement les combinaisons de caractères.

1voto

Stephan202 Points 27707

Je n'ai pas pu trouver de fonction intégrée pour cela (pour l'instant). Cependant, il existe une fonction reverse exemple en aller efficace :

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

Cela ne fonctionnera pas si a est de type string Cependant, les chaînes de caractères sont immuables en Go. Martin Clayton résout ce problème en séparant et en joignant une chaîne de caractères donnée. La solution suivante est une solution alternative, qui ne fonctionne malheureusement que pour les chaînes ascii :

import "strings"

func Reverse(input string) string {
  b := strings.Bytes(input);
  for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
    b[i], b[j] = b[j], b[i]
  }
  return string(b);
}

1voto

Oliver Mason Points 386

Cela semble un peu "détourné", et probablement pas très efficace, mais illustre comment l'interface Reader peut être utilisée pour lire des chaînes de caractères. Les IntVectors semblent également très bien adaptés comme tampons lorsqu'on travaille avec des chaînes utf8.

Il serait encore plus court si l'on omettait la partie "taille" et que l'on insérait dans le vecteur par insertion, mais je suppose que cela serait moins efficace, car le vecteur entier doit alors être repoussé d'une unité à chaque fois qu'une nouvelle rune est ajoutée.

Cette solution fonctionne sans aucun doute 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());
}

1 votes

Pourquoi ajoutez-vous tous ces points-virgules à la fin ?

2 votes

@olivier-mason Il est temps d'apprendre à connaître gofmt lors du partage de code Go.

1 votes

Cette réponse date d'il y a huit ans.

0voto

Jonathan Wright Points 3146

Une version qui, je pense, fonctionne sur l'unicode. Elle est construite 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);
}

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