Bagaimana cara membalikkan string di Go?

103

Bagaimana cara membalikkan string sederhana di Go?

pengguna211499
sumber
1
Sejauh yang saya pahami, solusi yang diberikan di bawah ini tidak berfungsi dengan karakter yang dikomposisi sebelumnya atau menggabungkan, seperti memberi, a+´bukan á. Saya bertanya-tanya bagaimana hal itu dapat diperhitungkan, tanpa menormalkannya.
siritinga
Jika Anda bingung dengan sejumlah besar jawaban serupa, periksa patokan saya .
Salvador Dali

Jawaban:

94

Di Go1 rune adalah tipe bawaan.

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
sumber
4
Anda tidak dapat menggunakan len () di Go untuk mengetahui panjang string / Array / Slice dll ... Berikut alasannya? - len () di Go berarti ukuran input dalam byte. Itu tidak sesuai dengan panjangnya. - Tidak semua rune utf8 berukuran sama. Bisa berupa 1, 2, 4, atau 8. - Anda harus menggunakan metode paket unicode / ut8 RuneCountInString untuk mendapatkan panjang rune.
Anvesh Checka
15
@AnveshChecka, itu salah. Lihat golang.org/pkg/builtin/#len - len () pada sepotong pasti mengembalikan jumlah elemen, bukan ukuran dalam byte. Sepotong rune adalah cara yang benar untuk melakukannya.
chowey
3
@ рытфолд Ini tidak dapat dilakukan dengan menggabungkan karakter. Lihat play.golang.org/p/sBgZAV7gCb , karakter penggabung tidak ditukar dengan basisnya.
chowey
53

Russ Cox, di milis golang-nut , menyarankan

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)
}
pengguna181548
sumber
20
Saya suka bagaimana mereka memaksa Anda untuk berpikir tentang pengkodean.
György Andrasek
10
di luar topik: mengapa [golang-kacang] dan bukan [gila]?
Jimmy
2
Wah, apa sudah habis dengan penugasan ganda saat membalik? Menarik. Sekarang, pikirkan tentang string dengan jumlah rune yang tidak rata. Yang tengah mendapat perlakuan khusus, dengan hasil akhir yang benar. :) Sebuah pengoptimalan kecil yang menarik yang tidak langsung terpikirkan oleh saya.
Kissaki
4
Saya tidak mengerti mengapa konversi ini menjadi rune, mengapa tidak rune:=[]rune(input)?
siritinga
1
Anda tidak perlu loop for range pertama. keluaran: = [] rune (masukan); n: = len (output) Dan Anda tidak membutuhkan rune = rune [0: n]
dvallejo
29

Ini berfungsi, tanpa semua penyia-nyiaan dengan fungsi:

func Reverse(s string) (result string) {
  for _,v := range s {
    result = string(v) + result
  }
  return 
}
Simon
sumber
6
Meskipun berhasil, karena string tidak dapat diubah, ini sangat tidak efisien. Saya telah memposting solusi yang lebih efisien.
peterSO
5
Ini jauh terlalu mudah dimengerti. Buat lebih sulit :-) (dan, "plus satu" untuk
melanjutkannya
2
Ini adalah jawaban terbaik kecuali membalikkan string adalah hambatan Anda.
Banjocat
1
@dolmen - mengapa ini tidak menangani penggabungan karakter? range pada string mengembalikan rune yang merupakan codepoint.
Stan R.
1
@Tokopedia Rune bukanlah mesin terbang. Mesin terbang dapat dibuat dari beberapa titik kode / rune. Lihat reedbeta.com/blog/programmers-intro-to-unicode/#combining-marks Titik kode yang terbalik akan melampirkan tanda gabungan ke titik kode dasar yang berbeda.
dolmen
14

Ini bekerja pada string unicode dengan mempertimbangkan 2 hal:

  • range bekerja pada string dengan menghitung karakter unicode
  • string dapat dibangun dari irisan int di mana setiap elemen adalah karakter unicode.

Jadi begini:

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'
sumber
Saya akan menetapkan i:=len(o)-1dan kemudian melipat untuk menjadi satu baris for _, c:=range s { o[i--]=c; }. Man I HATE karena tanpa tanda kurung - apakah ini diizinkan:for(_, c:=range s) { o[i--]=c; }
Lawrence Dol
Bisakah Anda menjelaskan apa yang _ lakukan?
Lawrence Dol
6
@Software_Monkey: o [i--] = c tidak diizinkan di Go. - dan ++ adalah pernyataan, bukan ekspresi. _ berarti membuang (mengabaikan) variabel itu.
Randy Sugianto 'Yuku'
1
dengan go 1.1+ itu mengembalikan kesalahan dalam baris string ([] int), jika sebaliknya [] jenis rune digunakan untuk o, semua berfungsi
Otuk
1
@yuku: Masih gagal pada s: = "Les Mise \ u0301rables"
Stefan Steiger
13

Dari proyek contoh Go: golang / example / stringutil / reverse.go , oleh 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)
}

Pergi Playground untuk membalikkan string

Setelah membalikkan string "bròwn", hasil yang benar haruslah "nwòrb", bukan "nẁorb".
Perhatikan kuburan di atas huruf o.


Untuk mempertahankan Unicode yang menggabungkan karakter seperti "as⃝df̅" dengan hasil terbalik "f̅ds⃝a",
lihat kode lain yang tercantum di bawah ini:

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

Ivan Chau
sumber
2
Terima kasih telah mengklarifikasi perbedaan dari stackoverflow.com/a/10030772/3093387 - tampaknya kedua solusi ini berbeda dalam cara menangani string seperti "bròwn".
josliber
Terima kasih telah menyebutkan solusi Rosettacode yang menangani penggabungan karakter
dolmen
11

Saya memperhatikan pertanyaan ini ketika Simon memposting solusinya yang, karena string tidak dapat diubah, sangat tidak efisien. Solusi lain yang diusulkan juga cacat; mereka tidak bekerja atau tidak efisien.

Berikut adalah solusi efisien yang berfungsi, kecuali jika string tersebut bukan UTF-8 yang valid atau string berisi kombinasi karakter.

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
sumber
1
string kembali (rune) Bekerja juga.
3
@ Tommy: Tidak, return string(runes)tidak bekerja untuk semua kasus.
peterSO
bisakah Anda menjelaskan lebih banyak tentang mengapa demikian? Saya membuat program pendek dan berfungsi di sana, tetapi mungkin kasus-kasus yang Anda bicarakan tidak terpicu di sana? play.golang.org/p/yk1sAwFjol
1
@ Tommy: Program singkat Anda hanya menunjukkan bahwa karakter NUL adalah NOP ketika dikirim ke printer atau terminal. Fungsi Reverse2 Anda gagal untuk string berenkode UTF-8 non-ASCII. Saya telah merevisi program singkat Anda sehingga menjadi tes yang valid: play.golang.org/p/Ic5G5QEO93
peterSO
Satu lagi "solusi" yang salah yang tidak menangani penggabungan karakter dengan benar.
dolmen
9

Ada terlalu banyak jawaban di sini. Beberapa di antaranya merupakan duplikat yang jelas. Tetapi bahkan dari yang kiri, sulit untuk memilih solusi terbaik.

Jadi saya memeriksa jawabannya, membuang yang tidak berfungsi untuk unicode dan juga menghapus duplikat. Saya membandingkan orang yang selamat untuk menemukan yang tercepat. Jadi, inilah hasil dengan atribusi (jika Anda melihat jawaban yang saya lewatkan, tetapi layak ditambahkan, silakan memodifikasi tolok ukur):

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

Jadi inilah metode tercepat oleh 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)
}

Untuk beberapa alasan saya tidak dapat menambahkan patokan, jadi Anda dapat menyalinnya dari PlayGround(Anda tidak dapat menjalankan tes di sana). Ubah namanya dan jalankango test -bench=.

Salvador Dali
sumber
Tak satu pun dari "solusi" tersebut menangani penggabungan tanda dengan benar.
dolmen
6

Saya menulis Reversefungsi berikut yang menghormati pengkodean UTF8 dan karakter gabungan:

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

Saya melakukan yang terbaik untuk membuatnya seefisien dan semudah mungkin. Idenya sederhana, melintasi rune mencari karakter gabungan kemudian membalikkan rune karakter gabungan di tempat. Setelah kita menutupi semuanya, balikkan rune dari seluruh string juga di tempatnya.

Katakanlah kami ingin membalikkan string ini bròwn. Itu òdiwakili oleh dua rune, satu untuk the odan satu untuk unicode ini \u0301ayang mewakili "kuburan".

Untuk kesederhanaan, mari kita gambarkan string seperti ini bro'wn. Hal pertama yang kami lakukan adalah mencari karakter gabungan dan membalikkannya. Jadi sekarang kita punya tali br'own. Akhirnya, kami membalikkan seluruh string dan berakhir dengan nwo'rb. Ini dikembalikan kepada kami sebagainwòrb

Anda dapat menemukannya di sini https://github.com/shomali11/util jika Anda ingin menggunakannya.

Berikut beberapa kasus uji untuk menunjukkan beberapa skenario yang berbeda:

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
sumber
3

Membangun di atas saran asli Stephan202, dan tampaknya berfungsi untuk string 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, "" );
}

Alternatifnya, tidak menggunakan paket string, tetapi bukan '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
sumber
+1. Itu bekerja. Tetapi saya harus mengatakan bahwa agak aneh (untuk saat ini) bahwa pemisahan dan penggabungan diperlukan untuk tugas yang begitu sederhana ...
Stephan202
@martin: maaf untuk hasil edit itu. Saya tidak sengaja menempelkan jawaban terbaru saya dalam pertanyaan Anda ... saya sangat malu .
Stephan202
@ Stephan - tidak masalah. Saya menambahkan solusi alternatif, berdasarkan fungsi string paket Bytes.
martin clayton
@Nosradena: Saya memutar balik dalam menit yang sama (saya terkejut melihat bahwa Martin memperbarui jawabannya dengan teks yang persis sama yang baru saja saya tulis ... dan kemudian saya sadar;)
Stephan202
@martin: versi kedua terlihat lebih baik jika Anda bertanya kepada saya :)
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

Menggunakan strings.Builder sekitar 3 kali lebih cepat daripada menggunakan penggabungan string

Vlad Bezden
sumber
1
Saya bertanya-tanya, mengapa pertanyaan ini tidak memiliki suara positif meskipun merupakan jawaban yang paling akurat
Nilesh
3

Ini sangat berbeda, saya akan mengatakan pendekatan yang lebih fungsional, tidak tercantum di antara jawaban lain:

func reverse(s string) (ret string) {
    for _, v := range s {
        defer func(r rune) { ret += string(r) }(v)
    }
    return
}
Vladimir Bauer
sumber
Saya cukup yakin ini bukan solusi tercepat, tetapi ini menunjukkan bagaimana variabel pengembalian retdisimpan dalam penutupan untuk diproses lebih lanjut, dengan setiap fungsi penangguhan.
Vladimir Bauer
Lambat dan tidak menangani penggabungan karakter dengan benar.
dolmen
1
Saya tidak yakin seberapa cepat itu, tapi itu indah.
donatJ
Performa yang satu ini dapat ditingkatkan di Go 1.14. Setidaknya catatan rilis mengklaim tidak memiliki overhead penangguhan.
Vladimir Bauer
2

Ini adalah implementasi tercepat

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
sumber
Apakah Anda membandingkan solusi sebelum mengklaim bahwa ini adalah implementasi tercepat?
Denys Séguret
ya saya lakukan, itulah mengapa kode BenchmarkReverse ada :). Namun saya tidak memiliki hasil lagi.
rmuller
Solusi cepat, tetapi masih salah karena tidak menangani penggabungan karakter dengan benar.
dolmen
Apakah benar karena @dolmen mengatakan bahwa ini tidak menangani penggabungan karakter? Apakah ada solusi di sini yang bisa melakukannya?
geraldss
2

Kode ini mempertahankan urutan penggabungan karakter secara utuh, dan harus bekerja dengan masukan UTF-8 yang tidak valid juga.

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

Ini bisa menjadi sedikit lebih efisien jika primitif unicode / norm mengizinkan iterasi melalui batas-batas string tanpa mengalokasikan. Lihat juga https://code.google.com/p/go/issues/detail?id=9055 .

rog
sumber
Tidak ada "input UTF-8 yang tidak valid" dalam nilai string: saat mengonversi dari []byteke stringGo menggantikan "input UTF-8 yang tidak valid" dengan titik kode yang valid \uFFFD.
dolmen
Saya tidak mengerti komentar di atas. Apakah Anda mengatakan bahwa perilaku kode ini salah ketika disajikan dengan string yang berisi UTF-8 yang tidak valid?
rog
Tidak. Saya katakan bahwa UTF-8 yang tidak valid saat Go stringtidak ada. Tapi itu bisa ada di []byte.
dolmen
String Go dapat berisi utf-8 yang tidak valid sama banyaknya dengan [] byte. Misalnya: play.golang.org/p/PG0I4FJfEN
rog
2

Jika Anda perlu menangani cluster grafem, gunakan modul unicode atau 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
}
masakielastik
sumber
Saya ingin memberi Anda 1.000 suara positif. Semua penerapan lain di laman ini membalikkan STRING secara tidak benar (STRING BUKAN merupakan urutan karakter).
Stefan Steiger
Ini tidak berhasil. Jika Anda membalikkan dua kali string Anda tidak mendapatkan string asli. Menggabungkan Diaeresis (\ u0308) terkemuka, yang digunakan dalam contoh ini digabungkan dengan karakter sebelumnya yang membuat umlaut ganda 'a' saat dibalik. Jika stroutput dikutip, itu mengubah kutipan terkemuka!
Joshua Kolden
2

Anda juga dapat mengimpor implementasi yang sudah ada:

import "4d63.com/strrev"

Kemudian:

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

Atau untuk membalikkan string termasuk unicode yang menggabungkan karakter:

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

Implementasi ini mendukung pengurutan yang benar dari multibyte unicode dan karakter combing ketika dibalik.

Catatan: Fungsi pembalikan string bawaan dalam banyak bahasa pemrograman tidak mempertahankan penggabungan, dan mengidentifikasi penggabungan karakter memerlukan waktu eksekusi yang jauh lebih lama.

Leigh McCulloch
sumber
1

Ini pasti bukan solusi yang paling hemat memori, tetapi untuk solusi aman UTF-8 "sederhana" berikut ini akan menyelesaikan pekerjaan dan tidak merusak rune.

Menurut pendapat saya, ini paling mudah dibaca dan dipahami di halaman ini.

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

    return
}
donatJ
sumber
1

Dua metode berikut berjalan lebih cepat daripada solusi tercepat yang mempertahankan penggabungan karakter , meskipun itu tidak berarti saya kehilangan sesuatu dalam pengaturan benchmark saya.

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

Metode kedua terinspirasi oleh ini

//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
sumber
Inilah yang Anda lewatkan dalam tolok ukur Anda: solusi Anda lebih cepat karena tidak mempertahankan penggabungan karakter. Tidak adil membandingkan mereka.
dolmen
1

CATATAN: Jawaban ini dari 2009, jadi mungkin ada solusi yang lebih baik di luar sana sekarang.


Tampak agak 'bundaran', dan mungkin tidak terlalu efisien, tetapi menggambarkan bagaimana antarmuka Reader dapat digunakan untuk membaca dari string. IntVectors juga tampaknya sangat cocok sebagai buffer saat bekerja dengan string utf8.

Ini akan menjadi lebih pendek ketika meninggalkan bagian 'ukuran', dan penyisipan ke dalam vektor dengan Sisipkan, tapi saya rasa itu akan kurang efisien, karena seluruh vektor kemudian perlu didorong kembali oleh satu setiap kali rune baru ditambahkan .

Solusi ini pasti berfungsi dengan karakter 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
sumber
Mengapa Anda menambahkan semua titik koma di belakang itu?
Morteza R
@ olivier-mason Saatnya mempelajari tentang gofmt saat berbagi kode Go.
dolmen
1
Jawaban itu dari delapan tahun lalu.
Oliver Mason
@OliverMason Tidak ada kata terlambat untuk memperbaiki (atau menghapus) solusi yang tidak sempurna.
dolmen
0

Sebuah versi yang menurut saya berfungsi pada unicode. Itu dibangun di atas fungsi 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
sumber
0

rune adalah tipe, jadi gunakanlah. Selain itu, Go tidak menggunakan titik koma.

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
sumber
Ini menggunakan titik koma ketika pertanyaan itu diposting.
OneOfOne
Satu lagi "solusi" yang salah yang tidak menangani penggabungan karakter dengan benar.
dolmen
0

Untuk string sederhana dimungkinkan untuk menggunakan konstruksi seperti itu:

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

Ini solusi lainnya:

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

Namun, solusi yazu di atas lebih elegan karena ia membalikkan []runepotongan pada tempatnya.

Jabba
sumber
-1

Namun Solusi Lain (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
sumber
-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, "")
}

Uji

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

Keluaran

Input: GO je úžasné!
Output: nsažú ej OG
PASS
ok      github.com/alesr/reverse-string 0.098s
Alessandro Resta
sumber
Ini berfungsi jika input ada di NFC. Tetapi seperti kebanyakan solusi salah lainnya di sini, itu tidak berfungsi dengan menggabungkan karakter.
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
sumber