Goで文字列を逆にする方法は?


102

Goで単純な文字列を反転するにはどうすればよいですか?


1
私が理解している限り、以下の解決策は、のa+´代わりにを与えるような、事前に構成された文字や結合文字では機能しませんá。それを正規化せずにどのように考慮に入れることができるのでしょうか。
siritinga 2014

回答:


94

Go1では、ルーンは組み込み型です。

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
Goでlen()を使用して文字列/配列/スライスなどの長さを確認することはできません。これはなぜですか?-Goのlen()は、バイト単位の入力のサイズを意味します。長さに対応していません。-すべてのutf8のルーンが同じサイズであるとは限りません。ルーンの長さを取得するには、unicode / ut8パッケージのメソッドRuneCountInStringを使用する必要があります。
Anvesh Checka

15
@AnveshChecka、それは間違っています。golang.org/pkg/builtin/#lenを参照してください。スライスのlen()は、バイト単位のサイズではなく、要素の数を確実に返します。ルーンのスライスはそれを行う正しい方法です。
Chowey、2015年

3
@рытфолдこれは文字の結合では機能しません。play.golang.org/p/sBgZAV7gCbを参照してください。結合するキャラクターはそのベースと交換されません。
Chowey、2015年

53

golang-nutsメーリングリストのRuss Coxが示唆しています

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

20
私は彼らがあなたにエンコーディングについて考えるように強制する方法が好きです。
ジェルジAndrasek

9
off-topic:なぜ[go-nuts]ではなく[golang-nuts]なのですか?
ジミー、

2
うわー、リバート時のwtfの二重割り当ては?面白い。ここで、ルーンの数が一定でない文字列について考えます。真ん中のものは特別な扱いを受けますが、結局のところ正しい結果が得られます。:)すぐには考えられなかった、興味深い小さな最適化。
Kissaki

4
なぜこのルーン文字に変換するのかわかりませんが、どうしてrune:=[]rune(input)ですか?
siritinga 2014

1
最初のforループは必要ありません。出力:= [] rune(入力); n:= len(output)そして、rune = rune [0:n]は必要ありません
dvallejo

29

これは機能しますが、関数をいじくる必要はありません。

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

6
動作しますが、文字列は不変であるため、非常に非効率的です。より効率的なソリューションを投稿しました。
peterSO

5
これは非常に簡単に理解できます。難しくします:-)(そして、それを
やり直す

2
文字列を逆にすることがボトルネックでない限り、これが最良の答えです。
Banjocat 2015年

1
@dolmen-これはなぜ結合文字を処理しないのですか?文字列の範囲は、コードポイントであるルーンを返します。
スタン

1
@StanR。ルーンはグリフではありません。グリフは、複数のコードポイント/ルーンで構成できます。reedbeta.com/blog/programmers-intro-to-unicode/#combining-marksを参照してください。コードポイントを反転すると、結合マークが別のベースコードポイントに付加されます。
ドルメン

14

これは、2つのことを考慮して、Unicode文字列で機能します。

  • 範囲は、Unicode文字を列挙することによって文字列に作用します
  • stringは、各要素がUnicode文字であるintスライスから構築できます。

だからここに行く:

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

i:=len(o)-1forを割り当ててから、1行に折りfor _, c:=range s { o[i--]=c; }ます。かっこなしで私は嫌いな男-これは許可されています:for(_, c:=range s) { o[i--]=c; }
Lawrence Dol

_が何をするのか説明してもらえますか?
ローレンスドル

6
@Software_Monkey:o [i--] = cはGoでは許可されていません。-と++はステートメントであり、式ではありません。_は、その変数を破棄(無視)することを意味します。
Randy Sugianto 'Yuku'

1
go 1.1+では、string([] int)行にエラーを返します。代わりに[] runeタイプをoに使用すると、すべて機能します
Otuk

1
@yuku:それでもs:= "Les Mise \ u0301rables"で失敗する
Stefan Steiger

13

Goサンプルプロジェクトから:Andlang Gerrandによるgolang / example / stringutil / reverse.go

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

文字列を逆転させるためにプレイグラウンドに行く

文字列「bròwn」を逆にすると、正しい結果は「nẁorb」ではなく「nwòrb」になります。
文字oの上にある墓に注意してください。


「as⃝df̅」などのUnicode結合文字を逆の結果「f̅ds⃝a」で保持するには、
以下にリストされている別のコードを参照してください。

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


2
stackoverflow.com/a/10030772/3093387との違いを明確にしていただきありがとうございます。これら2つのソリューションでは、「bròwn」のような文字列の処理方法が異なるようです。
josliber

組み合わせ文字を処理するロゼッタコードソリューションについて言及していただきありがとうございます
ドルメン

11

Simon彼のソリューションを投稿しときにこの質問に気付きました。これは、文字列は不変であるため、非常に非効率的です。他の提案された解決策にも欠陥があります。機能しないか、非効率的です。

文字列が有効なUTF-8でない場合、または文字列に結合文字が含まれている場合を除いて、機能する効率的なソリューションを次に示します。

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
return string(runes)も機能します。

3
@トミー:いいえ、return string(runes)すべてのケースで機能するわけではありません。
peterSO 2013

それがなぜかについてもう少し説明してもらえますか?私は短いプログラムを作成し、そこで機能しましたが、あなたが話しているそれらのケースはそこでトリガーされないのでしょうか?play.golang.org/p/yk1sAwFjol

1
@Tommy:この短いプログラムは、NUL文字がプリンターまたは端末に送信されたときにNOPであることを示しているだけです。非ASCII UTF-8エンコードされた文字列に対して、Reverse2関数が失敗します。有効なテストになるように短いプログラムを修正しました:play.golang.org/p/Ic5G5QEO93
peterSO

結合文字を適切に処理しないもう1つの誤った「解決策」。
ドルメン

9

ここでは答えが多すぎます。それらのいくつかは明らかに重複しています。しかし、左からでも最適なソリューションを選択するのは困難です。

だから私は答えを調べ、ユニコードでは機能しないものを捨て、重複も削除しました。私は生存者をベンチマークして最速を見つけました。だからここに帰属の結果があります(私が見逃した回答に気付いたが、追加する価値がある場合は、ベンチマークを自由に変更してください):

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

だからここに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)
}

何らかの理由でベンチマークを追加できないので、そこからコピーできますPlayGround(そこでテストを実行することはできません)。名前を変更して実行しますgo test -bench=.


これらの「ソリューション」はいずれも、マークの結合を正しく処理しません。
ドルメン

6

ReverseUTF8エンコーディングと結合文字を尊重する次の関数を作成しました。

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

私はできる限り効率的で読みやすいように最善を尽くしました。アイデアは単純で、ルーン文字をトラバースして結合文字を探し、次に結合文字のルーン文字を元に戻します。すべてをカバーしたら、ストリング全体のルーン文字も逆に配置します。

この文字列を逆にしたいとしますbròwnò2つのルーンのための1で表されo、これはUnicodeのための1つの\u0301a「墓」を表しています。

簡単にするために、このような文字列を表現しましょうbro'wn。まず最初に、結合された文字を探し、それらを逆にします。これで文字列ができましたbr'own。最後に、文字列全体を逆にして、で終わりnwo'rbます。これは、nwòrb

使用したい場合は、https://github.com/shomali11/utilで見つけることができます。

ここでは、いくつかの異なるシナリオを示すテストケースをいくつか示します。

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

3

Stephan202の最初の提案に基づいて構築されており、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, "" );
}

文字列パッケージを使用せず、 '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 );
}

+1。うまくいきます。しかし、私は分割と結合がそのような単純なタスクに必要であるというのは(今のところ)かなり奇妙であると言わなければなりません...
Stephan202

@martin:その編集は申し訳ありません。私が誤ってあなたの質問に私の更新の答えを貼り付けた... 私は非常に恥ずかしいです
Stephan202 2009年

@Stephan-問題ありません。文字列パッケージのBytes関数に基づく代替ソリューションを追加しました。
マーティンクレイトン

@Nosradena:私は同じ分以内にロールバックしました(Martinが自分が書いたばかりのテキストとまったく同じテキストで彼の回答を更新したのを見て驚いた...そして、それが私に
現れた

@martin:2つ目のバージョンは、私に聞いた方が見栄えがよくなります:)
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

strings.Builderの使用は、文字列連結の使用よりも約3倍高速です。


1
なぜ、この質問は最も正確な回答であるにもかかわらず、賛成票がないのでしょうか
Nilesh

3

これはかなり異なります。他の回答にリストされていない、より機能的なアプローチと言えます。

func reverse(s string) (ret string) {
    for _, v := range s {
        defer func(r rune) { ret += string(r) }(v)
    }
    return
}

私はそれが最速の解決策ではないことを確信していますが、それはret、各遅延関数によって、戻り変数がさらなる処理のためにクロージャに保持される方法を示しています。
Vladimir Bauer

低速で、文字の結合を適切に処理しません。
ドルメン

1
それがどれほど速いかはわかりませんが、それは美しいです。
donatJ 2016

これのパフォーマンスはGo 1.14で改善されるかもしれません。少なくともリリースノートには、据え置きのオーバーヘッドがゼロであると記載されています。
ウラジミールバウアー

2

これは最速の実装です

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

最速の実装だと主張する前に、ソリューションのベンチマークを行いましたか?
DenysSéguret2014

はい、私はそうしました、それがBenchmarkReverseコードが存在する理由です:)。しかし、私はもう結果がありません。
rmuller 2014

高速な解決策ですが、結合文字を適切に処理しないため、依然として間違っています。
ドルメン

@dolmenがこれは結合文字を処理しないと言っているので、本当ですか?ここで解決策はありますか?
geraldss

2

このコードは、結合文字のシーケンスをそのまま保持し、無効なUTF-8入力でも機能するはずです。

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

unicode / normプリミティブで、割り当てを行わずに文字列の境界を反復できる場合は、少し効率的かもしれません。https://code.google.com/p/go/issues/detail?id=9055ご覧ください


文字列値には、そのような「無効なUTF-8入力」はありません。[]byteからstringGo に変換すると、「無効なUTF-8入力」が有効なコードポイントに置き換えられます\uFFFD
ドルメン

上記のコメントが理解できません。無効なUTF-8を含む文字列が提示されたときに、このコードの動作が間違っていると言っていますか?
カエル2017

いいえ。Goに無効なUTF-8 stringは存在しないと言っています。しかし、それはに存在できます[]byte
ドルメン

Go文字列には、[]バイトと同じだけの無効なutf-8を含めることができます。例:play.golang.org/p/PG0I4FJfEN
rog

2

書記素クラスタを処理する必要がある場合は、unicodeまたは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
}

私はあなたに1'000票を与えたいのですが。このページの他のすべての実装は、STRINGを誤って反転します(STRINGは文字のシーケンスではありません)。
Stefan Steiger 2016年

これは機能しません。文字列を二重に逆にすると、元の文字列は得られません。この例で使用されている先頭の結合分音記号(\ u0308)は、前の文字と結合して、反転すると二重ウムラウト「a」を作成します。str出力が引用符で囲まれている場合は、先行引用符が変更されます!
ジョシュアコルデン

2

既存の実装をインポートすることもできます。

import "4d63.com/strrev"

次に:

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

または、Unicode結合文字を含む文字列を反転するには:

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

これらの実装では、Unicodeマルチバイトの正しい順序と、反転したときのコーミング文字がサポートされています。

注:多くのプログラミング言語の組み込みの文字列逆関数は結合を保持せず、結合文字を識別するには実行時間が大幅に長くなります。


1

確かに、これは最もメモリ効率の高いソリューションではありませんが、「シンプルな」UTF-8セーフソリューションの場合、次のようにすれば、ルーン文字が壊れることはありません。

私の意見では、このページで最も読みやすく、理解しやすいと思います。

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

    return
}

1

次の2つの方法は、結合文字を保持する最速のソリューションよりも高速に実行されますが、それでも、ベンチマーク設定で何かが欠けているとは限りません。

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

これに触発された2番目の方法

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

ベンチマークで足りないものは次のとおりです。結合文字が保持されないため、ソリューションが高速になります。それらを比較するのは不公平です。
ドルメン

1

注:この回答は2009年からのものであるため、おそらく今より良い解決策があります。


少し「回り道」に見え、おそらくあまり効率的ではありませんが、Readerインターフェイスを使用して文字列から読み取る方法を示しています。IntVectorは、utf8文字列を処理するときのバッファとしても非常に適しているようです。

「サイズ」の部分を省略し、Insertを使用してベクターに挿入する場合はさらに短くなりますが、新しいルーンが追加されるたびにベクター全体を1つずつ押し戻す必要があるため、効率が低下すると思います。

このソリューションは確実に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());
}

末尾のセミコロンをすべて追加するのはなぜですか?
モルテザR

@ olivier-mason Goコードを共有するときにgofmtについて学ぶ時が来ました。
ドルメン

1
その答えは8年前のものでした。
Oliver Mason

@OliverMason不完全なソリューションを修正(または削除)するのに遅すぎることはありません。
ドルメン

0

私がユニコードで動作すると思うバージョン。これは、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);
}

0

ルーンはタイプなので、使いましょう。さらに、Goはセミコロンを使用しません。

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

その質問が投稿されたとき、それはセミコロンを使用しました。
OneOfOne

結合文字を適切に処理しないもう1つの誤った「解決策」。
ドルメン

0

以下のコードを試してください:

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

詳細については 、http://golangcookbook.com/chapters/strings/reverse/
およびhttp://www.dotnetperls.com/reverse-string-goを確認してください


0

単純な文字列の場合、次のような構造を使用できます。

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

-1

ここにさらに別の解決策があります:

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

ただし、上のyazuの解決策は、[]runeスライスを元に戻すため、よりエレガントです。


-1

さらに別のソリューション(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)
}

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

テスト

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

出力

Input: GO je úžasné!
Output: nsažú ej OG
PASS
ok      github.com/alesr/reverse-string 0.098s

これは、入力がNFCにある場合に機能します。しかし、ここで他のほとんどの間違ったソリューションと同様に、文字の組み合わせでは機能しません。
ドルメン

-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
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.