Як повернути рядок у Go?


103

Як можна повернути простий рядок у Go?


1
Наскільки я розумію, наведені нижче рішення не працюють із заздалегідь складеними або комбінуючими символами, як, наприклад, давання a+´замість á. Цікаво, як це можна було б врахувати, не нормалізуючи це.
siritinga

Якщо вас плутає величезна кількість подібних відповідей, перевірте мій показник .
Сальвадор Далі

Відповіді:


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
ви не можете використовувати len () в Go, щоб дізнатися довжину рядка / Array / Slice тощо ... Ось чому? - len () в Go означає розмір вводу в байтах. Це не відповідає його довжині. - Не всі руни utf8 мають однаковий розмір. Це може бути 1, 2, 4 або 8. - Ви повинні використовувати метод пакета unicode / ut8 RuneCountInString, щоб отримати довжину руни.
Анвеш Чецька

15
@AnveshChecka, це неправильно. Дивіться golang.org/pkg/builtin/#len - len () на фрагменті безумовно повертає кількість елементів, а не розмір у байтах. Шматочок рун - це правильний спосіб зробити це.
chowey

3
@ рытфолд Це не працює з об'єднанням символів. Див. Play.golang.org/p/sBgZAV7gCb , характер, що поєднує, не змінюється своєю базою.
chowey

53

Расс Кокс із списку розсилки голанг-горіхів пропонує

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
Мені подобається, як вони змушують вас думати про кодування.
Дьорджі Андрасек

10
поза темою: чому це [голанг-горіхи], а не [горіхи]?
Джиммі

2
Нічого, wtf готовий до подвійного призначення при перевороті назад? Цікаво. А тепер подумайте про струну з нерівною кількістю рун. Середній отримує спеціальне лікування, але з правильним кінцевим результатом все-таки. :) Цікава цікава оптимізація, яку я б не подумав одразу.
Кіссакі

4
Я не розумію, чому це перетворення в руну, чому ні rune:=[]rune(input)?
siritinga

1
Вам не потрібен перший цикл діапазону. вихід: = [] руна (вхід); n: = len (вихід) І вам не потрібна руна = руна [0: n]
dvallejo

29

Це спрацьовує, не замислюючись про функції:

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

6
Хоча це працює, оскільки рядки незмінні, це дуже неефективно. Я розмістив більш ефективне рішення.
peterSO

5
Це багато занадто легко зрозуміти. Зробити це складніше :-) (і "плюс один", щоб просто почати працювати)
Roboprog

2
Це найкраща відповідь, якщо обернені рядки не є вашим вузьким місцем.
Banjocat

1
@dolmen - чому б це не обробляло поєднання символів? діапазон на рядку повертає руну, яка є кодовою точкою.
Стен Р.

1
@StanR. Руна - це не гліф. Гліф може бути зроблений з декількох кодових точок / рун. Див. Reedbeta.com/blog/programmers-intro-to-unicode/#combining-marks Повернення кодових точок додасть комбінуючі позначки до іншої базової кодової точки.
долмен

14

Це працює на рядках Unicode, враховуючи 2 речі:

  • дальність працює на рядку шляхом перерахування символів unicode
  • рядок може бути побудований з int-фрагментів, де кожен елемент є символом unicode.

Отже, ось що:

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)-1а потім скласти для в один рядок for _, c:=range s { o[i--]=c; }. Людина, яку я ненавиджу за без дужок - це дозволено:for(_, c:=range s) { o[i--]=c; }
Лоуренс Дол

Чи можете ви пояснити, що робить _
Лоуренс Дол

6
@Software_Monkey: o [i--] = c заборонено в Go. - і ++ - це заяви, а не вирази. _ означає відкинути (проігнорувати) цю змінну.
Ренді Сугіанто 'Юку'

1
з go 1.1+ він повертає помилку в рядку ([] int), якщо замість цього [] використовується тип руни для o, все працює
Otuk

1
@yuku: Ще не вдається на s: = "Les Mise \ u0301rables"
Стефан Штайгер

13

З Go прикладів проектів: golang / наприклад / StringUtil / reverse.go , Ендрю 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)
}

Перейдіть на майданчик для зворотного струни

Після обертання рядка "bròwn" правильним результатом має бути "nwòrb", а не "nẁorb".
Зверніть увагу на могилу над буквою о.


Для збереження Unicode, що поєднує символи, такі як "as⃝df̅" із зворотним результатом "f̅ds⃝a",
зверніться до іншого коду, переліченого нижче:

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


2
Дякуємо, що роз’яснили відмінність від stackoverflow.com/a/10030772/3093387 - схоже, що ці два рішення відрізняються тим, як вони обробляють рядки, як “bròwn”.
josliber

Дякуємо, що згадали про рішення Rosettacode, яке обробляє поєднання символів
dolmen

11

Я помітив це питання, коли Саймон виклав своє рішення, яке, оскільки рядки незмінні, дуже неефективне. Інші запропоновані рішення також є недоліками; вони не працюють або вони неефективні.

Ось ефективне рішення, яке працює, за винятком випадків, коли рядок недійсний 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
також повертається рядок (руни).

3
@Tommy: Ні, return string(runes)працює не у всіх випадках.
peterSO

Ви можете, будь ласка, пояснити трохи більше, чому це так? Я створив коротку програму, і вона там працює, але, можливо, ті випадки, про які ти говориш, там не запускаються? play.golang.org/p/yk1sAwFjol

1
@Tommy: Ваша коротка програма просто демонструє, що символ NUL є NOP при надсиланні на принтер або термінал. Функція Reverse2 не працює для рядків, кодованих не ASCII UTF-8. Я переглянув вашу коротку програму, щоб вона була дійсним тестом: play.golang.org/p/Ic5G5QEO93
peterSO

Ще одне неправильне "рішення", яке не справляється з об'єднанням символів належним чином.
долмен

9

Тут занадто багато відповідей. Деякі з них - це чіткі дублікати. Але навіть з лівого боку важко вибрати найкраще рішення.

Тому я переглянув відповіді, викинув той, який не працює для unicode, а також видалив дублікати. Я орієнтував людей, що вижили, щоб знайти найшвидшого. Ось ось результати з атрибуцією (якщо ви помітили відповіді, які я пропустив, але варто додати, не соромтеся змінити орієнтир):

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

Я написав таку Reverseфункцію, яка поважає кодування UTF8 та комбіновані символи:

// 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. Оно òпредставлено двома рунами, одна для цього oі одна для цього унікоду, \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

@Stephan - не проблема. Я додав альтернативне рішення на основі функції рядків пакету рядків.
Мартін Клейтон

@Nosradena: Я відкотився протягом тієї самої хвилини (я був здивований, побачивши, що Мартін оновив свою відповідь точно тим самим текстом, який я щойно написав ..., а потім на мене зійшло;)
Stephan202

@martin: друга версія виглядає краще, якщо ви запитаєте мене :)
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
Цікаво, чому це питання не має жодних результатів, незважаючи на найбільш точну відповідь
Нілеш,

3

Тут зовсім інший, я б сказав, більш функціональний підхід, не вказаний серед інших відповідей:

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

Я впевнений, що це не найшвидше рішення, але це показує, як змінна повернення retзберігається в закритому режимі для подальшої обробки кожною функцією відкладання.
Володимир Бауер

Повільно і не справляється з комбінуванням символів належним чином.
долмен

1
Я не впевнений, наскільки це швидко, але це красиво.
donatJ

Продуктивність цього може бути покращена в 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)
    }
}

Ви орієнтувались на рішення, перш ніж заявляли, що це найшвидша реалізація?
Denys Séguret

так, я це зробив, тому код BenchmarkReverse присутній :). Однак у мене більше немає результатів.
rmuller

Швидке рішення, але все-таки неправильне, оскільки воно не справляється з об'єднанням символів належним чином.
долмен

Це правда, як @dolmen каже, що це не вирішує поєднання символів? Чи є тут рішення, яке це робить?
геральдс

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/isissue/detail?id=9055 .


Там немає такого «неприпустимого UTF-8 введення» в строкових значеннях: при переході від []byteдо stringGo замінює «неприпустимий UTF-8» вхід в законну силу елемента коду \uFFFD.
долмен

Я не розумію вищезазначеного коментаря. Ви хочете сказати, що поведінка цього коду неправильна, коли він представлений рядком, що містить недійсний UTF-8?
рог

Ні. Я кажу, що недійсний UTF-8 в режимі "Go 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
}

Я хотів би надати вам 1000 нагород. Усі інші реалізації на цій сторінці неправильно скасовують STRING (STRING НЕ є послідовністю символів).
Стефан Штайгер

Це не працює. Якщо ви подвійно обернете рядок, ви не отримаєте початковий рядок. Провідний діаберез, що поєднує (\ u0308), використаний у цьому прикладі, поєднується з попередніми символами, створюючи подвійний умовний "а" при зворотному переході. Якщо strвиводиться котирування, воно змінює провідну пропозицію!
Джошуа Колден

2

Ви також можете імпортувати існуючу реалізацію:

import "4d63.com/strrev"

Тоді:

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

Або скасувати рядок, включаючи символи, що поєднують унікод:

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

Ці реалізації підтримують правильне впорядкування багатобайтових однобайтових та комбінування символів при їх відміні.

Примітка. Вбудовані функції зворотних рядків у багатьох мовах програмування не зберігають комбінування, а ідентифікація об'єднаних символів вимагає значно більше часу на виконання.


1

Це, безумовно, не найефективніше пам'ять, але для "простого" безпечного рішення UTF-8 наступне допоможе виконати роботу і не зламати руни.

На мою думку, це найчитабельніше і зрозуміліше на сторінці.

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

    return
}

1

Наступні два методи працюють швидше, ніж найшвидше рішення, яке зберігає поєднання символів , хоча це не означає, що я щось пропускаю в налаштуваннях орієнтиру.

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

Другий натхненний цим метод

//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 можна використовувати для читання з рядків. IntVectors також здаються дуже підходящими як буфери при роботі з рядками utf8.

Це було б ще коротше, коли вийде частина "розміру" та вставлення у вектор за допомогою Insert, але, мабуть, це було б менш ефективно, оскільки весь вектор тоді потрібно відштовхувати по одній щоразу, коли додається нова руна .

Це рішення безумовно працює з 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());
}

Чому ви додаєте всі ці крапки з комою?
Morteza R

@ olivier-mason Настав час дізнатися про gofmt при спільному використанні коду Go.
долмен

1
Ця відповідь була з восьми років тому.
Олівер Мейсон

@OliverMason Ніколи не пізно виправити (або видалити) недосконале рішення.
долмен

0

Версія, на яку я думаю, працює на unicode. Він побудований на функціях 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

Ще одне неправильне "рішення", яке не справляється з об'єднанням символів належним чином.
долмен

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

Ще одне рішення (тм):

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
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.