Как перевернуть строку в Go?


103

Как мы можем перевернуть простую строку в Go?


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

Если вас смущает огромное количество похожих ответов, посмотрите мой тест .
Сальвадор Дали

Ответы:


95

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

15
@AnveshChecka, это неверно. См. Golang.org/pkg/builtin/#len - len () на срезе определенно возвращает количество элементов, а не размер в байтах. Кусочек рун - правильный способ сделать это.
chowey

4
@ рытфолд Не работает с объединением символов. См. Play.golang.org/p/sBgZAV7gCb , комбинирующий символ не меняется местами с его базой.
chowey

53

Расс Кокс из списка рассылки golang-nut предлагает

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
Вау, что за двойное назначение при движении задним ходом? Интересный. Теперь представьте себе цепочку с нечетным количеством рун. К среднему обращаются по-особенному, но все же с правильным конечным результатом. :) Небольшая интересная оптимизация, о которой я бы сразу не подумал.
Kissaki

4
Я не понимаю, почему это преобразование в руны, почему бы и нет rune:=[]rune(input)?
siritinga 05

1
Вам не нужен первый цикл для диапазона. вывод: = [] руна (ввод); n: = len (output) И вам не нужна rune = rune [0: n]
dvallejo

30

Это работает, без всякой возни с функциями:

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

7
Хотя это работает, поскольку строки неизменяемы, это очень неэффективно. Я опубликовал более эффективное решение.
peterSO

5
Это много слишком легко понять. Сделать это сложнее :-) (и «плюс один» за то, что просто
продолжил

2
Это лучший ответ, если только перестановка струн не является вашим узким местом.
Banjocat

1
@dolmen - почему это не обрабатывает объединение символов? диапазон в строке возвращает руну, которая является кодовой точкой.
Стэн Р.

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

14

Это работает со строками Unicode, учитывая 2 вещи:

  • диапазон работает со строкой, перечисляя символы Юникода
  • Строка может быть построена из срезов типа 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)-1а затем свернул for в одну строку for _, c:=range s { o[i--]=c; }. Человек, которого я НЕНАВИЖУ, без круглых скобок - это разрешено:for(_, c:=range s) { o[i--]=c; }
Лоуренс Дол

Не могли бы вы объяснить, что делает _?
Лоуренс Дол

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

1
с go 1.1+ он возвращает ошибку в строке ([] int), если вместо o используется тип руны [], все работает
Otuk

1
@yuku: Все еще терпит неудачу на s: = "Les Mise \ u0301rables"
Стефан Штайгер

13

Примеры проектов из Go: 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» правильным результатом должно быть «nwòrb», а не «nẁorb».
Обратите внимание на могилу над буквой o.


Для сохранения Unicode-сочетания символов, таких как «as⃝df̅» с обратным результатом «f̅ds⃝a»,
обратитесь к другому коду, указанному ниже:

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


2
Спасибо за разъяснение отличия от stackoverflow.com/a/10030772/3093387 - кажется, что эти два решения отличаются тем, как они обрабатывают строки, такие как «bròwn».
josliber

Спасибо за упоминание решения Rosettacode, которое обрабатывает объединение символов
дольмен

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

Еще одно неправильное «решение», которое неправильно обрабатывает комбинирование символов.
дольмен

10

Здесь слишком много ответов. Некоторые из них - явные дубликаты. Но даже из левого варианта сложно выбрать лучшее решение.

Я просмотрел ответы, выбросил тот, который не работает для юникода, а также удалил дубликаты. Я сравнил выживших, чтобы найти самых быстрых. Итак, вот результаты с атрибуцией (если вы заметили ответы, которые я пропустил, но которые стоит добавить, не стесняйтесь изменять тест):

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

4
//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
Интересно, почему у этого вопроса нет голосов, несмотря на самый точный ответ
Нилеш

4

Вот совсем другой, я бы сказал, более функциональный подход, не перечисленный среди других ответов:

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. По крайней мере, в примечаниях к выпуску утверждается, что у них нет накладных расходов на отсрочку.
Владимир Бауэр

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

Альтернативный вариант, без использования строкового пакета, но не «безопасный для юникода»:

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

@ Стефан - без проблем. Я добавил альтернативное решение, основанное на функции Bytes пакета strings.
Мартин Клейтон

@Nosradena: Я откатился назад в течение той же минуты (я был удивлен, увидев, что Мартин обновил свой ответ точно таким же текстом, который я только что написал ... и затем меня осенило;)
Stephan202

@martin: вторая версия выглядит лучше, если вы спросите меня :)
Stephan202

3

Это самая быстрая реализация

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 говорит, что это не обрабатывает объединение символов? Есть ли здесь решение?
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)
}

Было бы немного эффективнее, если бы примитивы юникода / нормы позволяли выполнять итерацию через границы строки без выделения. См. Также https://code.google.com/p/go/issues/detail?id=9055 .


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

Я не понимаю приведенный выше комментарий. Вы говорите, что поведение этого кода неверно, когда он представлен строкой, содержащей недопустимый UTF-8?
Rog

Нет. Я говорю, что недопустимый 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
}

Я хочу дать вам 1'000 голосов за. Все другие реализации на этой странице неправильно меняют СТРОКУ (СТРОКА НЕ является последовательностью символов).
Stefan Steiger

Это не работает. Если вы дважды перевернете строку, вы не получите исходную строку. Ведущий комбинированный диэрезис (\ u0308), используемый в этом примере, объединяется с предыдущими символами, образуя двойной умляут «а» при обратном. Если strвыводится в кавычках, это изменяет начальную цитату!
Джошуа Колден

2

Вы также можете импортировать существующую реализацию:

import "4d63.com/strrev"

Затем:

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

Или перевернуть строку, содержащую объединяющие символы Unicode:

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 Никогда не поздно исправить (или удалить) несовершенное решение.
dolmen

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

Еще одно неправильное «решение», которое неправильно обрабатывает комбинирование символов.
dolmen

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

0

Простой штрих с rune:

func ReverseString(s string) string {
    runes := []rune(s)
    size := len(runes)
    for i := 0; i < size/2; i++ {
        runes[size-i-1], runes[i] = runes[i],  runes[size-i-1]
    }
    return string(runes)
}

func main() {
    fmt.Println(ReverseString("Abcdefg 汉语 The God"))
}
: doG ehT 语汉 gfedcbA

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

Однако вышеприведенное решение Язу более элегантно, поскольку он переворачивает []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
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.