Как перевернуть строку в Go? - PullRequest
83 голосов
/ 18 ноября 2009

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

Ответы [ 25 ]

3 голосов
/ 18 ноября 2009

Основывается на оригинальном предложении 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, "" );
}

Альтернативно, не использует пакет strings, но не '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 );
}
2 голосов
/ 24 октября 2017

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

import "4d63.com/strrev"

Тогда:

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

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

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

В этих реализациях поддерживается правильное упорядочение многобайтовых символов Юникода и символов гребенки при обращении.

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

2 голосов
/ 24 июня 2016

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

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

Кредиты

2 голосов
/ 18 ноября 2009

Выглядит немного «окольными», и, вероятно, не очень эффективно, но иллюстрирует, как интерфейс Reader может использоваться для чтения из строк. IntVectors также кажутся очень подходящими в качестве буферов при работе со строками utf8.

Было бы еще короче, если пропустить часть 'size' и вставить в вектор с помощью 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());
}
2 голосов
/ 03 июня 2016

Это, безусловно, не самое эффективное решение для памяти, но для "простого" безопасного решения UTF-8 следующее выполнит работу и не сломает руны.

Это, на мой взгляд, самый читаемый и понятный на странице.

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

    return
}
1 голос
/ 18 января 2018

Для простых струн можно использовать такую ​​конструкцию:

func Reverse(str string) string {
    if str != "" {
        return Reverse(str[1:]) + str[:1]
    }
    return ""   
}
1 голос
/ 03 сентября 2016

Следующие два метода работают быстрее, чем самое быстрое решение, которое сохраняет объединение символов , хотя это не значит, что я что-то упустил в моей настройке теста.

//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 голос
/ 29 июня 2016

попробуйте ниже код:

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

1 голос
/ 06 апреля 2012

Руна - это тип, так что используйте его. Более того, 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))
}
1 голос
/ 03 ноября 2014

Этот код сохраняет последовательности объединения символов без изменений, и должен работать и с неверным вводом 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.

...