Go'da bir dize nasıl tersine çevrilir?


103

Go'da basit bir dizeyi nasıl tersine çevirebiliriz?


1
Anladığım kadarıyla, aşağıda verilen çözümler, vermek a+´yerine vermek gibi önceden oluşturulmuş veya birleştirilen karakterlerle çalışmıyor á. Normalleştirmeden bunun nasıl dikkate alınabileceğini merak ediyorum.
siritinga

Çok sayıda benzer cevapla kafanız karıştıysa, kıyaslamamı kontrol edin .
Salvador Dali

Yanıtlar:


94

Go1'de rune yerleşik bir tiptir.

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
Bir string / Array / Slice vb.'nin uzunluğunu bulmak için Go'da len () kullanamazsınız ... İşte nedeni? - Go'daki len (), girdinin bayt cinsinden boyutu anlamına gelir. Boyuna karşılık gelmiyor. - Utf8'in tüm runeleri aynı boyutta değil. 1, 2, 4 veya 8 olabilir. - Rün uzunluğunu elde etmek için unicode / ut8 paketinin RuneCountInString yöntemini kullanmalısınız.
Anvesh Checka

15
@AnveshChecka, bu yanlış. Bir dilimdeki golang.org/pkg/builtin/#len - len () bölümüne bakın , bayt cinsinden boyutu değil, kesinlikle öğe sayısını döndürür. Bunu yapmanın doğru yolu bir dilim runedir.
chowey

3
@ рытфолд Bu, karakterlerin birleştirilmesiyle çalışmaz. Play.golang.org/p/sBgZAV7gCb'ye bakın , birleştiren karakter tabanıyla değiştirilmez.
chowey

53

Russ Cox golang-fındık posta listesinde , anlaşılacağı

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
Sizi kodlamalar hakkında düşünmeye zorlamaları hoşuma gidiyor.
György Andrasek

10
konu dışı: neden [golang-nut] ve [go-nut] değil?
Jimmy

2
Wow, wtf geri giderken çift atama yapıyor mu? İlginç. Şimdi, eşit olmayan sayıda run içeren bir dizeyi düşünün. Ortadaki, her şeye rağmen doğru sonuçla özel muamele görür. :) Hemen aklıma gelmeyen ilginç bir optimizasyon.
Kissaki

4
Neden bu dönüşümün rune olduğunu anlamıyorum, neden olmasın rune:=[]rune(input)?
siritinga

1
Aralık döngüsü için ilkine ihtiyacınız yok. çıktı: = [] rune (giriş); n: = len (çıkış) Ve rün = rün gerekmez [0: n]
dvallejo

29

Bu, işlevlerle uğraşmadan çalışır:

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

7
Çalışırken, dizeler değişmez olduğu için çok verimsizdir. Daha verimli bir çözüm yayınladım.
peterSO

5
Bu çok fazla kolay anlaşılması. Zorlaştır :-) (ve sadece devam etmek için "artı bir")
Roboprog

2
Dizeleri ters çevirmek, darboğazınız olmadığı sürece bu en iyi cevaptır.
Banjocat

1
@dolmen - bu neden karakterlerin birleştirilmesini işlemiyor? dizge üzerindeki bir aralık kod noktası olan bir rune döndürür.
Stan R.

1
@StanR. Bir rune bir glif değildir. Bir glif, birden çok kod noktasından / koşudan yapılabilir. Bkz. Reedbeta.com/blog/programmers-intro-to-unicode/#combining-marks Kod noktalarını ters çevirmek , farklı bir temel kod noktasına birleştirme işaretleri iliştirir.
dolmen

14

Bu, 2 şeyi dikkate alarak unicode dizeleri üzerinde çalışır:

  • aralık , unicode karakterleri numaralandırarak dize üzerinde çalışır
  • dize, her öğenin bir unicode karakter olduğu int dilimlerinden oluşturulabilir.

İşte başlıyor:

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

For'u atar i:=len(o)-1ve sonra tek bir satıra katlardım for _, c:=range s { o[i--]=c; }. Adamım, parantez olmadan nefret ediyorum - buna izin verilir:for(_, c:=range s) { o[i--]=c; }
Lawrence Dol

_'Nin ne yaptığını açıklayabilir misiniz?
Lawrence Dol

6
@Software_Monkey: o [i--] = c'ye Go'da izin verilmez. - ve ++ ifadelerdir, ifadeler değildir. _, bu değişkeni atmak (yok saymak) anlamına gelir.
Randy Sugianto 'Yuku'

1
go 1.1+ ile string ([] int) satırında hata döndürür, eğer onun yerine [] rune türü o için kullanılırsa, tüm işler
Otuk

1
@yuku: s: = "Les Mise \ u0301rables" üzerinde hala başarısız
Stefan Steiger

13

Gönderen golang / example / stringutil / reverse.go: Git örnek projelerin Andrew Gerrand tarafından

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

Bir dizeyi ters çevirmek için Playground'a gidin

"Bròwn" dizesini tersine çevirdikten sonra, doğru sonuç "nẁorb" değil "nwòrb" olmalıdır.
O harfinin üzerindeki mezara dikkat edin.


Ters sonucu "f̅ds⃝a" olan "as⃝df̅" gibi Unicode birleşik karakterleri korumak için,
lütfen aşağıda listelenen başka bir koda bakın:

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


2
Stackoverflow.com/a/10030772/3093387 arasındaki farkı açıkladığınız için teşekkürler - bu iki çözümün "bròwn" gibi dizeleri nasıl ele aldıklarına göre farklılık gösterdiği görülüyor.
josliber

Karakterleri birleştiren Rosettacode çözümünden bahsettiğiniz için teşekkürler
dolmen

11

Simon , dizeler değişmez olduğu için çok verimsiz olan çözümünü yayınladığında bu soruyu fark ettim . Önerilen diğer çözümler de kusurludur; çalışmıyorlar veya verimsizler.

Dize geçerli UTF-8 olmadığı veya dizenin birleştirici karakterler içermesi dışında çalışan verimli bir çözüm aşağıda verilmiştir.

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) da çalışır.

3
@Tommy: Hayır, return string(runes)her durumda çalışmaz.
peterSO

bunun neden olduğu konusunda biraz daha açıklar mısınız? Kısa bir program yaptım ve orada çalışıyor, ama belki de bahsettiğiniz bu davalar orada tetiklenmiyor? play.golang.org/p/yk1sAwFjol

1
@Tommy: Kısa programınız yalnızca NUL karakterinin bir yazıcıya veya terminale gönderildiğinde bir NOP olduğunu gösterir. Reverse2 işleviniz, ASCII olmayan UTF-8 kodlu dizeler için başarısız oluyor. Kısa programınızı, geçerli bir test olacak şekilde gözden
geçirdim

Karakterleri doğru şekilde birleştirmeyen bir başka yanlış "çözüm".
dolmen

9

Burada çok fazla cevap var. Bazıları açık kopyalar. Ancak soldan bile en iyi çözümü seçmek zor.

Bu yüzden cevapları gözden geçirdim, unicode için çalışmayan ve aynı zamanda kopyaları sildim. En hızlı olanı bulmak için hayatta kalanları kıyasladım. İşte atıfta bulunan sonuçlar (gözden kaçırdığım ancak eklemeye değer yanıtları fark ederseniz, karşılaştırmayı değiştirmekten çekinmeyin):

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

İşte rmuller'ın en hızlı yöntemi :

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

Bazı nedenlerden dolayı bir kıyaslama ekleyemiyorum, bu yüzden onu kopyalayabilirsiniz PlayGround(orada testler çalıştıramazsınız). Yeniden adlandırın ve çalıştırıngo test -bench=.


Bu "çözümlerin" hiçbiri, birleştirme işaretlerini doğru şekilde işlemez.
dolmen

6

ReverseUTF8 kodlamasına ve birleşik karakterlere saygı duyan aşağıdaki işlevi yazdım :

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

Bunu olabildiğince verimli ve okunabilir hale getirmek için elimden geleni yaptım. Fikir basittir, birleşik karakterleri aramak için runelerin arasından geçin, ardından birleşik karakterlerin runlarını yerinde tersine çevirin. Hepsini örttüğümüzde, tüm dizinin rünlerini de yerinde ters çevirin.

Bu dizeyi tersine çevirmek istediğimizi varsayalım bròwn. òİki runes için biri tarafından temsil edilir ove bu unicode diğeri \u0301a"vahim" temsil eder.

Basit olması için, dizeyi şu şekilde temsil edelim bro'wn. Yaptığımız ilk şey, birleşik karakterleri aramak ve onları tersine çevirmek. Şimdi ipimiz var br'own. Son olarak, tüm dizgiyi tersine çeviririz ve sonunda nwo'rb. Bu bize şu şekilde iade edilirnwòrb

Kullanmak isterseniz burada https://github.com/shomali11/util bulabilirsiniz .

Birkaç farklı senaryoyu gösteren bazı test senaryoları şunlardır:

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'nin orijinal önerisini temel alan ve unicode dizeleri için işe yaradığı görülüyor:

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, dizeler paketi kullanmadan, ancak 'unicode güvenli' değil:

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. Bu işe yarıyor. Ama şunu söylemeliyim ki bölme ve birleştirme bu kadar basit bir görev için gerekliydi (şimdilik) ...
Stephan202

@martin: Bu düzenleme için üzgünüm. Güncellenmiş cevabımı yanlışlıkla sorunuza yapıştırdım ... çok utandım .
Stephan202

@Stephan - sorun değil. Dizeler paketi Bytes işlevine göre alternatif bir çözüm ekledim.
martin clayton

@Nosradena: Aynı dakika içinde geri döndüm (Martin'in cevabını tam olarak yazdığım metinle güncellediğini görünce şaşırdım ... ve sonra aklıma geldi;)
Stephan202

@martin: Bana sorarsan ikinci versiyon daha iyi görünüyor :)
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

Dizeleri kullanmak. Oluşturucu, dize birleştirme kullanmaktan yaklaşık 3 kat daha hızlıdır


1
Bu soru cevap en doğru olmasına rağmen hiçbir upvotes vardır neden merak
Nilesh

3

İşte oldukça farklı, diğer cevaplar arasında listelenmeyen daha işlevsel bir yaklaşım söyleyebilirim:

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

Bunun en hızlı çözüm olmadığından oldukça eminim, ancak dönüş değişkeninin rether erteleme işlevi tarafından daha fazla işlem için nasıl kapalı tutulduğunu gösteriyor .
Vladimir Bauer

Yavaş ve karakterleri doğru şekilde birleştirmiyor.
dolmen

1
Bunun ne kadar hızlı olduğundan emin değilim ama çok güzel.
donatJ

Bunun performansı Go 1.14'te geliştirilebilir. En azından sürüm notları , sıfır erteleme ek yüküne sahip olduğunu iddia ediyor.
Vladimir Bauer

2

Bu en hızlı uygulama

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

Bunun en hızlı uygulama olduğunu iddia etmeden önce çözümleri karşılaştırdınız mı?
Denys Séguret

evet yaptım, bu yüzden BenchmarkReverse kodu mevcut :). Ancak artık sonuçlara sahip değilim.
rmuller

Hızlı çözüm, ancak karakterleri doğru şekilde birleştiremediği için yine de yanlış.
dolmen

@Dolmen, bunun karakterleri birleştirmeyi işlemediğini söylediği için doğru mu? Burada işe yarayan bir çözüm var mı?
geraldss

2

Bu kod, birleşik karakter dizilerini bozulmadan korur ve geçersiz UTF-8 girdisiyle de çalışmalıdır.

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 ilkelleri, ayırmadan bir dizgenin sınırları boyunca yinelemeye izin verirse, biraz daha verimli olabilirdi. Ayrıca bkz . Https://code.google.com/p/go/issues/detail?id=9055 .


Dize değerlerinde böyle bir "geçersiz UTF-8 girişi" yoktur: ' []byteden stringGo'ya dönüştürürken, "geçersiz UTF-8 girdisini" geçerli bir kod noktasıyla değiştirir \uFFFD.
dolmen

Yukarıdaki yorumu anlamıyorum. Geçersiz UTF-8 içeren bir dizeyle sunulduğunda bu kodun davranışının yanlış olduğunu mu söylüyorsunuz?
rog

Hayır string. Go'da geçersiz UTF-8'in olmadığını söylüyorum . Ama bir []byte.
dolmen

Bir Go dizesi, bir [] baytı kadar tam olarak geçersiz utf-8 içerebilir. Örneğin: play.golang.org/p/PG0I4FJfEN
rog

2

Grapheme kümelerini işlemeniz gerekiyorsa, unicode veya regexp modülünü kullanın.

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
}

Size 1000 olumlu oy vermek istiyorum. Bu sayfadaki diğer tüm uygulamalar bir STRING'i yanlış bir şekilde tersine çevirir (STRING bir karakter dizisi DEĞİLDİR).
Stefan Steiger

Bu çalışmıyor. Dizeyi iki kez ters çevirirseniz, orijinal dizeyi elde edemezsiniz. Bu örnekte kullanılan baştaki Birleştirme Diyaerezi (\ u0308), ters çevrildiğinde çift çift nokta "a" oluşturarak önceki karakterlerle birleşir. Eğer strçıkış alıntı o lider alıntı değiştirir!
Joshua Kolden

2

Ayrıca mevcut bir uygulamayı da içe aktarabilirsiniz:

import "4d63.com/strrev"

Sonra:

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

Veya unicode birleştiren karakterler içeren bir dizeyi ters çevirmek için:

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

Bu uygulamalar, unicode çok baytının doğru sıralanmasını ve tersine çevrildiğinde karakterlerin taranmasını destekler.

Not: Birçok programlama dilindeki yerleşik dizi ters işlevleri, birleştirmeyi korumaz ve birleşik karakterlerin tanımlanması, önemli ölçüde daha fazla yürütme süresi gerektirir.


1

Kesinlikle bellek açısından en verimli çözüm değil, ancak "basit" UTF-8 güvenli bir çözüm için aşağıdakiler işi bitirecek ve runları bozmayacaktır.

Bence sayfadaki en okunaklı ve anlaşılır olanı.

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

    return
}

1

Aşağıdaki iki yöntem , karakterleri birleştirmeyi koruyan en hızlı çözümden daha hızlı çalışır , ancak bu, kıyaslama kurulumumda bir şeyleri kaçırdığım anlamına gelmez.

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

İkinci yöntem esinlenerek bu

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

Karşılaştırmanızda eksik olan şey şudur: çözümünüz daha hızlıdır çünkü karakter kombinasyonunu korumaz. Onları karşılaştırmak haksızlık.
dolmen

1

NOT: Bu cevap 2009 yılına aittir, bu nedenle şimdiye kadar muhtemelen daha iyi çözümler vardır.


Biraz 'dolambaçlı' görünüyor ve muhtemelen çok verimli değil, ancak Reader arayüzünün dizelerden okumak için nasıl kullanılabileceğini gösteriyor. IntVector'lar ayrıca utf8 dizeleriyle çalışırken tampon olarak çok uygun görünmektedir.

'Boyut' kısmını dışarıda bıraktığınızda ve Ekleme ile vektöre yerleştirildiğinde daha da kısa olacaktır, ancak sanırım bu daha az verimli olacaktır, çünkü daha sonra tüm vektörün yeni bir rune eklendiğinde bir tane geri itilmesi gerekir. .

Bu çözüm kesinlikle utf8 karakterleriyle çalışır.

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

Neden tüm bu noktalı virgülleri ekliyorsunuz?
Morteza R

@ olivier-mason Go kodunu paylaşırken gofmt hakkında bilgi edinme zamanı.
dolmen

1
Bu cevap sekiz yıl önceydi.
Oliver Mason

@OliverMason Kusurlu bir çözümü düzeltmek (veya silmek) için asla geç değildir.
dolmen

0

Unicode üzerinde çalıştığını düşündüğüm bir sürüm. Utf8.Rune işlevleri üzerine kurulmuştur:

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

rune bir türdür, bu yüzden onu kullanın. Dahası, Go noktalı virgül kullanmaz.

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

Bu soru gönderildiğinde noktalı virgül kullandı.
OneOfOne

Karakterleri doğru şekilde birleştirmeyen bir başka yanlış "çözüm".
dolmen


0

Basit dizeler için böyle bir yapıyı kullanmak mümkündür:

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

-1

İşte başka bir çözüm:

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

Bununla birlikte, yazu'nun yukarıdaki çözümü, []runedilimi yerinde ters çevirdiği için daha zariftir .


-1

Yine Başka Bir Çözüm (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, "")
}

Ölçek

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

Çıktı

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

Bu, giriş NFC'de ise çalışır. Ancak buradaki diğer birçok yanlış çözüm gibi, karakterleri birleştirmekle işe yaramıyor.
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
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.