Go 中如何反转字符串?

发布于 2024-08-11 07:20:41 字数 28 浏览 6 评论 0原文

我们如何在 Go 中反转一个简单的字符串?

How can we reverse a simple string in Go?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

德意的啸 2024-08-18 07:20:42

带有rune的简笔画:

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

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

A simple stroke with rune:

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

func main() {
    fmt.Println(ReverseString("Abcdefg 汉语 The God"))
}
: doG ehT 语汉 gfedcbA
淡紫姑娘! 2024-08-18 07:20:42

这是完全不同的,我会说更实用的方法,未在其他答案中列出:

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

Here is quite different, I would say more functional approach, not listed among other answers:

func reverse(s string) (ret string) {
    for _, v := range s {
        defer func(r rune) { ret += string(r) }(v)
    }
    return
}
破晓 2024-08-18 07:20:42
func ReverseString(str string) string {
output :=""
for _, char := range str {
output = string(char) + output
}
return output
}

// "Luizpa" -> "apziuL"
// "123日本語" -> "語本日321"
// "⚽

func ReverseString(str string) string {
  output :=""
  for _, char := range str {
    output = string(char) + output
  }
  return output
}

// "Luizpa" -> "apziuL"
// "123日本語" -> "語本日321"
// "⚽????" -> "????⚽"
// "´a´b´c´" -> "´c´b´a´"
喜爱纠缠 2024-08-18 07:20:42

这是最快的实施

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

This is the fastest implementation

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)
    }
}
濫情▎り 2024-08-18 07:20:42

您还可以导入现有的实现:

import "4d63.com/strrev"

然后:

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

或者反转包含 unicode 组合字符的字符串:

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

这些实现在反转时支持 unicode 多字节和组合字符的正确排序。

注意:许多编程语言中的内置字符串反转函数不保留组合,并且识别组合字符需要更多的执行时间。

You could also import an existing implementation:

import "4d63.com/strrev"

Then:

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

Or to reverse a string including unicode combining characters:

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

These implementations supports correct ordering of unicode multibyte and combing characters when reversed.

Note: Built-in string reverse functions in many programming languages do not preserve combining, and identifying combining characters requires significantly more execution time.

凹づ凸ル 2024-08-18 07:20:42

该代码完整地保留了组合字符的序列,并且
也应该适用于无效的 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/issues /detail?id=9055

This code preserves sequences of combining characters intact, and
should work with invalid UTF-8 input too.

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

It could be a little more efficient if the unicode/norm primitives
allowed iterating through the boundaries of a string without
allocating. See also https://code.google.com/p/go/issues/detail?id=9055 .

中二柚 2024-08-18 07:20:42

如果需要处理字素簇,请使用 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
}

If you need to handle grapheme clusters, use unicode or regexp module.

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
}
ゝ偶尔ゞ 2024-08-18 07:20:42

它肯定不是最高效的内存解决方案,但对于“简单”的 UTF-8 安全解决方案,以下内容将完成工作并且不会破坏符文。

在我看来,这是该页面上最具可读性和最容易理解的内容。

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

    return
}

It's assuredly not the most memory efficient solution, but for a "simple" UTF-8 safe solution the following will get the job done and not break runes.

It's in my opinion the most readable and understandable on the page.

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

    return
}
安人多梦 2024-08-18 07:20:42

以下两种方法的运行速度比最快的保留组合字符的解决方案运行得更快,但这并不是说我错过了一些东西我的基准设置。

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

第二种方法的灵感来自this

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

The following two methods run faster than the fastest solution that preserve combining characters, though that's not to say I'm missing something in my benchmark setup.

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

Second method inspired by this

//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
×纯※雪 2024-08-18 07:20:42

简单、甜蜜、高性能

func reverseStr(str string) string {
  strSlice := []rune(str)  //converting to slice of runes
  length := len(strSlice)

  for i := 0; i < (length / 2); i++ {
      strSlice[i], strSlice[length-i-1] = strSlice[length-i-1], strSlice[i]
  }
  return string(strSlice)  //converting back to string
}

Simple, Sweet and Performant

func reverseStr(str string) string {
  strSlice := []rune(str)  //converting to slice of runes
  length := len(strSlice)

  for i := 0; i < (length / 2); i++ {
      strSlice[i], strSlice[length-i-1] = strSlice[length-i-1], strSlice[i]
  }
  return string(strSlice)  //converting back to string
}
变身佩奇 2024-08-18 07:20:42

注意:这个答案来自 2009 年,所以现在可能有更好的解决方案。


看起来有点“迂回”,并且可能不是很有效,但说明了如何使用 Reader 接口来读取字符串。在处理 utf8 字符串时,IntVector 似乎也非常适合作为缓冲区。

当省略“大小”部分并通过插入插入到向量中时,它会更短,但我想这会效率较低,因为每次添加新符文时,整个向量都需要向后推一。

这个解决方案肯定适用于 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());
}

NOTE: This answer is from 2009, so there are probably better solutions out there by now.


Looks a bit 'roundabout', and probably not very efficient, but illustrates how the Reader interface can be used to read from strings. IntVectors also seem very suitable as buffers when working with utf8 strings.

It would be even shorter when leaving out the 'size' part, and insertion into the vector by Insert, but I guess that would be less efficient, as the whole vector then needs to be pushed back by one each time a new rune is added.

This solution definitely works with utf8 characters.

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());
}
迷爱 2024-08-18 07:20:42
func Reverse(s string) string {
    r := []rune(s)
    var output strings.Builder
    for i := len(r) - 1; i >= 0; i-- {
        output.WriteString(string(r[i]))
    }

    return output.String()
}
func Reverse(s string) string {
    r := []rune(s)
    var output strings.Builder
    for i := len(r) - 1; i >= 0; i-- {
        output.WriteString(string(r[i]))
    }

    return output.String()
}
一向肩并 2024-08-18 07:20:42

按单词反转字符串是一个类似的过程。首先,我们将字符串转换为字符串数组,其中每个条目都是一个单词。接下来,我们对该数组应用正常的反向循环。最后,我们将结果重新组合成一个字符串,然后将其返回给调用者。

package main

import (
    "fmt"
    "strings"
)

func reverse_words(s string) string {
    words := strings.Fields(s)
    for i, j := 0, len(words)-1; i < j; i, j = i+1, j-1 {
        words[i], words[j] = words[j], words[i]
    }
    return strings.Join(words, " ")
}

func main() {
    fmt.Println(reverse_words("one two three"))
}

Reversing a string by word is a similar process. First, we convert the string into an array of strings where each entry is a word. Next, we apply the normal reverse loop to that array. Finally, we smush the results back together into a string that we can return to the caller.

package main

import (
    "fmt"
    "strings"
)

func reverse_words(s string) string {
    words := strings.Fields(s)
    for i, j := 0, len(words)-1; i < j; i, j = i+1, j-1 {
        words[i], words[j] = words[j], words[i]
    }
    return strings.Join(words, " ")
}

func main() {
    fmt.Println(reverse_words("one two three"))
}
平生欢 2024-08-18 07:20:42

另一个技巧是使用内置语言功能,例如 defer

package main

import "fmt"

func main() {
    var name string
    fmt.Scanln(&name)

    for _, char := range []rune(name) {
        defer fmt.Printf("%c", char) // <-- LIFO does it all for you
    }
}

Another hack is to use built-in language features, for example, defer:

package main

import "fmt"

func main() {
    var name string
    fmt.Scanln(&name)

    for _, char := range []rune(name) {
        defer fmt.Printf("%c", char) // <-- LIFO does it all for you
    }
}
白芷 2024-08-18 07:20:42

对于简单的字符串,可以使用这样的结构:

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

对于 Unicode 字符串,它可能如下所示:

func RecursiveReverse(str string) string {
    if str == "" {
        return ""
    }
    runes := []rune(str)
    return RecursiveReverse(string(runes[1:])) + string(runes[0])
}

For simple strings it possible to use such construction:

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

For Unicode strings it might look like this:

func RecursiveReverse(str string) string {
    if str == "" {
        return ""
    }
    runes := []rune(str)
    return RecursiveReverse(string(runes[1:])) + string(runes[0])
}
提笔书几行 2024-08-18 07:20:42

识别 unicode 代码点是一回事,但是字素簇又如何呢?

例如,

Recognising unicode code points is one thing, but how about grapheme clusters?

For example, ????‍☠️ is composed from 4 unicode code points / runes, and reversing such a string on the basis of runes will produce garbage. Not good.

Read more about Unicode segmentation in rivo/uniseg docs.

Here's the reversal of a string, using this package:

func reverseSlice[T any](s []T) {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
}

func reverse(s string) string {
    var grStrings []string

    gr := uniseg.NewGraphemes(s)
    for gr.Next() {
        grStrings = append(grStrings, gr.Str())
    }

    reverseSlice(grStrings)

    return strings.Join(grStrings, "")
}
飘然心甜 2024-08-18 07:20:42

我认为适用于 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);
}

A version which I think works on unicode. It is built on the utf8.Rune functions:

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);
}
霞映澄塘 2024-08-18 07:20:42

符文是一种类型,所以使用它。此外,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))
}

rune is a type, so use it. Moreover, Go doesn't use semicolons.

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))
}
戴着白色围巾的女孩 2024-08-18 07:20:42

尝试下面的代码:

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

try below code:

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

for more info check http://golangcookbook.com/chapters/strings/reverse/
and http://www.dotnetperls.com/reverse-string-go

隔纱相望 2024-08-18 07:20:42
    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
    }
    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
    }
左耳近心 2024-08-18 07:20:42

字符串在 golang 中是不可变的对象,与 C 不同,golang 中不可能进行原地反转。
使用 C ,你可以做类似的事情,

void reverseString(char *str) {
  int length = strlen(str)
  for(int i = 0, j = length-1; i < length/2; i++, j--)
  {
    char tmp = str[i];
    str[i] = str[j];
    str[j] = tmp;
  }
}

但是使用 golang,接下来的一个,首先使用 byte 将输入转换为字节,然后在反转后反转字节数组,在返回之前转换回字符串。仅适用于非 unicode 类型字符串。

package main

import "fmt"

func main() {
    s := "test123 4"
    fmt.Println(reverseString(s))
}

func reverseString(s string) string {
    a := []byte(s)
    for i, j := 0, len(s)-1; i < j; i++ {
        a[i], a[j] = a[j], a[i]
        j--
    }
    return string(a)
}

Strings are immutable object in golang, unlike C inplace reverse is not possible with golang.
With C , you can do something like,

void reverseString(char *str) {
  int length = strlen(str)
  for(int i = 0, j = length-1; i < length/2; i++, j--)
  {
    char tmp = str[i];
    str[i] = str[j];
    str[j] = tmp;
  }
}

But with golang, following one, uses byte to convert the input into bytes first and then reverses the byte array once it is reversed, convert back to string before returning. works only with non unicode type string.

package main

import "fmt"

func main() {
    s := "test123 4"
    fmt.Println(reverseString(s))
}

func reverseString(s string) string {
    a := []byte(s)
    for i, j := 0, len(s)-1; i < j; i++ {
        a[i], a[j] = a[j], a[i]
        j--
    }
    return string(a)
}
一抹苦笑 2024-08-18 07:20:41

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

In Go1 rune is a builtin type.

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)
}
一世旳自豪 2024-08-18 07:20:41

golang-nuts 邮件列表中的 Russ Cox 建议

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

Russ Cox, on the golang-nuts mailing list, suggests

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)
}
小伙你站住 2024-08-18 07:20:41

这是可行的,无需对函数进行任何处理:

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

This works, without all the mucking about with functions:

func Reverse(s string) (result string) {
  for _,v := range s {
    result = string(v) + result
  }
  return 
}
蘸点软妹酱 2024-08-18 07:20:41

这里有太多的答案。其中一些是明显的重复。但即使从左边的方案中,也很难选择最佳方案。

所以我浏览了答案,扔掉了对 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=.

There are too many answers here. Some of them are clear duplicates. But even from the left one, it is hard to select the best solution.

So I went through the answers, thrown away the one that does not work for unicode and also removed duplicates. I benchmarked the survivors to find the fastest. So here are the results with attribution (if you notice the answers that I missed, but worth adding, feel free to modify the benchmark):

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

So here is the fastest method by 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)
}

For some reason I can't add a benchmark, so you can copy it from PlayGround (you can't run tests there). Rename it and run go test -bench=.

猫瑾少女 2024-08-18 07:20:41

来自 Go 示例项目:golang/example/stringutil/reverse.go, 作者: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)
}

Go Playground 反转字符串

反转字符串“bròwn”后,正确的结果应该是“nwòrb”,而不是“nẁorb”。
注意字母o上方的坟墓。


为了保留 Unicode 组合字符,例如“as⃝df̅”与反向结果“f̅ds⃝a”,
请参考下面列出的另一个代码:

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

From Go example projects: golang/example/stringutil/reverse.go, by 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)
}

Go Playground for reverse a string

After reversing string "bròwn", the correct result should be "nwòrb", not "nẁorb".
Note the grave above the letter o.


For preserving Unicode combining characters such as "as⃝df̅" with reverse result "f̅ds⃝a",
please refer to another code listed below:

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

夢归不見 2024-08-18 07:20:41

这通过考虑两件事来处理 unicode 字符串:

  • range 通过枚举 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);
}

This works on unicode strings by considering 2 things:

  • range works on string by enumerating unicode characters
  • string can be constructed from int slices where each element is a unicode character.

So here it goes:

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);
}
枯寂 2024-08-18 07:20:41

我编写了以下尊重 UTF8 编码和组合字符的 Reverse 函数:

// 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,另一个代表代表“坟墓”的 unicode \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("

I wrote the following Reverse function which respects UTF8 encoding and combined characters:

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

I did my best to make it as efficient and readable as possible. The idea is simple, traverse through the runes looking for combined characters then reverse the combined characters' runes in-place. Once we have covered them all, reverse the runes of the entire string also in-place.

Say we would like to reverse this string bròwn. The ò is represented by two runes, one for the o and one for this unicode \u0301a that represents the "grave".

For simplicity, let's represent the string like this bro'wn. The first thing we do is look for combined characters and reverse them. So now we have the string br'own. Finally, we reverse the entire string and end up with nwo'rb. This is returned to us as nwòrb

You can find it here https://github.com/shomali11/util if you would like to use it.

Here are some test cases to show a couple of different scenarios:

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")
}
万人眼中万个我 2024-08-18 07:20:41

Simon发布他的解决方案,由于字符串是不可变的,效率非常低。其他提出的解决方案也存在缺陷;他们不工作或者效率低下。

这是一个有效的解决方案,除非字符串不是有效的 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 犬")))
}

I noticed this question when Simon posted his solution which, since strings are immutable, is very inefficient. The other proposed solutions are also flawed; they don't work or they are inefficient.

Here's an efficient solution that works, except when the string is not valid UTF-8 or the string contains combining characters.

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 犬")))
}
南冥有猫 2024-08-18 07:20:41
//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 倍

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

Using strings.Builder is about 3 times faster than using string concatenation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文