string 如何在 Go 中反转字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1752414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 00:34:04  来源:igfitidea点击:

How to reverse a string in Go?

stringgoreverse

提问by user211499

How can we reverse a simple string in Go?

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

回答by yazu

In Go1 rune is a builtin type.

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

回答by yazu

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

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

回答by Simon

This works, without all the mucking about with functions:

这是有效的,而无需考虑函数:

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

回答by Randy Sugianto 'Yuku'

This works on unicode strings by considering 2 things:

通过考虑两件事,这适用于 unicode 字符串:

  • rangeworks on string by enumerating unicode characters
  • string can be constructed from int slices where each element is a unicode character.
  • range通过枚举 unicode 字符来处理字符串
  • string 可以从 int 切片构造,其中每个元素都是一个 unicode 字符。

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

回答by Ivan Chau

From Go example projects: golang/example/stringutil/reverse.go, by Andrew Gerrand

来自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 for reverse a string

Go Playground 反转字符串

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

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



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

用于保留 Unicode 组合字符,例如“as?df?” 对于反向结果“f?ds?a”,
请参考下面列出的另一个代码:

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

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

回答by peterSO

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

Simon发布他的解决方案时,我注意到了这个问题,因为字符串是不可变的,所以效率非常低。其他提议的解决方案也有缺陷;它们不起作用或效率低下。

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

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

回答by Salvador Dali

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 resultswith attribution (if you notice the answers that I missed, but worth adding, feel free to modify the benchmark):

所以我浏览了答案,扔掉了那些不适用于 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

So here is the fastest method by rmuller:

所以这是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=.

出于某种原因,我无法添加基准测试,因此您可以从中复制它PlayGround(您不能在那里运行测试)。重命名并运行go test -bench=.

回答by Raed Shomali

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

我编写了以下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)
}

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 oand one for this unicode \u0301athat represents the "grave".

假设我们想反转这个字符串bròwn。的ò由两个符,一个用于表示o,一个用于这个unicode \u0301a,表示“严重”。

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

为简单起见,让我们像这样表示字符串bro'wn。我们做的第一件事是寻找组合字符并将它们反转。所以现在我们有了字符串br'own。最后,我们反转整个字符串并以nwo'rb. 这是返回给我们的nwòrb

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

如果你想使用它,你可以在这里找到它https://github.com/shomali11/util

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

回答by Vladimir Bauer

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
}

回答by martin clayton

Building on Stephan202's original suggestion, and appears to work for unicode strings:

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

Alternate, not using strings package, but not 'unicode-safe':

或者,不使用字符串包,但不使用“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 );
}