如何在Go中反转一个字符串?

huangapple go评论104阅读模式
英文:

How to reverse a string in Go?

问题

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

英文:

How can we reverse a simple string in Go?

答案1

得分: 148

在Go1中,rune是一种内置类型。

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 &lt; j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

答案2

得分: 63

Russ Cox,在 golang-nuts 邮件列表上,建议

package main 
import "fmt"
func main() { 
        input := "The quick brown 狐 jumped over the lazy 犬" 
        // 获取 Unicode 代码点。 
        n := 0
        rune := make([]rune, len(input))
        for _, r := range input { 
                rune[n] = r
                n++
        } 
        rune = rune[0:n]
        // 反转 
        for i := 0; i < n/2; i++ { 
                rune[i], rune[n-1-i] = rune[n-1-i], rune[i] 
        } 
        // 转换回 UTF-8。 
        output := string(rune)
        fmt.Println(output)
}
英文:

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

package main 
import &quot;fmt&quot;
func main() { 
        input := &quot;The quick brown 狐 jumped over the lazy 犬&quot; 
        // 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 &lt; 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)
}

答案3

得分: 54

这个代码可以正常工作,不需要对函数进行繁琐的操作:

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 
}

答案4

得分: 22

Go示例项目:golang/example/stringutil/reverse.go,作者是Andrew Gerrand

/*
版权所有 2014 Google Inc.
根据Apache许可证2.0版(“许可证”)授权;
除非符合许可证,否则您不得使用此文件。
您可以在以下网址获取许可证副本
     http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则以“原样”分发软件
没有任何明示或暗示的保证或条件。
有关特定语言的权限,请参阅许可证。
*/

// Reverse返回其参数字符串从左到右的逆序符文。
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 &quot;License&quot;);
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 &quot;AS IS&quot; 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 &lt; 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

答案5

得分: 17

这里有太多的答案。其中一些是明显的重复。但即使从剩下的答案中选择最佳解决方案也很困难。

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

答案6

得分: 15

这段代码适用于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);
}

答案7

得分: 13

我注意到这个问题是当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 &quot;fmt&quot;

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(&quot;Hello, 世界&quot;)))
	fmt.Println(Reverse(Reverse(&quot;The quick brown 狐 jumped over the lazy 犬&quot;)))
}

答案8

得分: 13

我写了以下的Reverse函数,它能够保持UTF8编码和组合字符的顺序:

// Reverse函数在保持UTF8编码和组合字符的顺序的同时,将输入字符串反转
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]) {
            // 反转组合字符
            reverse(textRunes[i:j], j-i)
        }

        i = j
    }

    // 反转整个数组
    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函数判断一个rune是否为标记符
func isMark(r rune) bool {
    return unicode.Is(unicode.Mn, r) || unicode.Is(unicode.Me, r) || unicode.Is(unicode.Mc, r)
}

我尽力使代码尽可能高效和易读。其思想很简单,遍历字符串的rune,寻找组合字符,然后原地反转组合字符的rune。一旦我们处理完所有组合字符,再原地反转整个字符串的rune。

假设我们想要反转字符串br&#242;wn&#242;由两个rune表示,一个是o,另一个是表示“重音符”的unicode \u0301a

为了简化,我们将字符串表示为bro&#39;wn。首先,我们寻找组合字符并将其反转。现在,我们得到了字符串br&#39;own。最后,我们反转整个字符串,得到nwo&#39;rb。这将作为nw&#242;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("&#128526;⚽"), "⚽&#128526;")
    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&#242;wn 狐 jumped over the lazy 犬"), "犬 yzal eht revo depmuj 狐 nw&#242;rb kciuq ehT")
}
英文:

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 &lt;= 1 {
    	return text
    }

	i, j := 0, 0
    for i &lt; textRunesLength &amp;&amp; j &lt; textRunesLength {
	    j = i + 1
	    for j &lt; textRunesLength &amp;&amp; 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 &lt; 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&#242;wn. The &#242; 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&#39;wn. The first thing we do is look for combined characters and reverse them. So now we have the string br&#39;own. Finally, we reverse the entire string and end up with nwo&#39;rb. This is returned to us as nw&#242;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(&quot;&quot;), &quot;&quot;)
	assert.Equal(t, Reverse(&quot;X&quot;), &quot;X&quot;)
	assert.Equal(t, Reverse(&quot;b\u0301&quot;), &quot;b\u0301&quot;)
	assert.Equal(t, Reverse(&quot;&#128526;⚽&quot;), &quot;⚽&#128526;&quot;)
	assert.Equal(t, Reverse(&quot;Les Mise\u0301rables&quot;), &quot;selbare\u0301siM seL&quot;)
	assert.Equal(t, Reverse(&quot;ab\u0301cde&quot;), &quot;edcb\u0301a&quot;)
	assert.Equal(t, Reverse(&quot;This `\xc5` is an invalid UTF8 character&quot;), &quot;retcarahc 8FTU dilavni na si `�` sihT&quot;)
	assert.Equal(t, Reverse(&quot;The quick br&#242;wn 狐 jumped over the lazy 犬&quot;), &quot;犬 yzal eht revo depmuj 狐 nw&#242;rb kciuq ehT&quot;)
}

答案9

得分: 12

//使用strings.Builder反转字符串。它比使用字符串拼接快大约3倍
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()
}

//使用字符串反转字符串
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&#39;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 &lt;= 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

答案10

得分: 7

一个简单的使用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 &lt; size&gt;&gt;1; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

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

答案11

得分: 6

这里有一个相当不同的方法,我会说是更加功能性的方法,不在其他答案中列出:

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
}

答案12

得分: 5

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

// "Luizpa" -> "apziuL"
// "123日本語" -> "語本日321"
// "⚽&#128526;" -> "&#128526;⚽"
// "&#180;a&#180;b&#180;c&#180;" -> "&#180;c&#180;b&#180;a&#180;"
英文:
func ReverseString(str string) string {
  output :=&quot;&quot;
  for _, char := range str {
    output = string(char) + output
  }
  return output
}

// &quot;Luizpa&quot; -&gt; &quot;apziuL&quot;
// &quot;123日本語&quot; -&gt; &quot;語本日321&quot;
// &quot;⚽&#128526;&quot; -&gt; &quot;&#128526;⚽&quot;
// &quot;&#180;a&#180;b&#180;c&#180;&quot; -&gt; &quot;&#180;c&#180;b&#180;a&#180;&quot;

答案13

得分: 4

这是最快的实现

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 &lt; size; {
		r, n := utf8.DecodeRuneInString(s[start:])
		start += n
		utf8.EncodeRune(buf[size-start:], r)
	}
	return string(buf)
}

const (
	s       = &quot;The quick brown 狐 jumped over the lazy 犬&quot;
	reverse = &quot;犬 yzal eht revo depmuj 狐 nworb kciuq ehT&quot;
)

func TestReverse(t *testing.T) {
	if Reverse(s) != reverse {
		t.Error(s)
	}
}

func BenchmarkReverse(b *testing.B) {
	for i := 0; i &lt; b.N; i++ {
		Reverse(s)
	}
}

答案14

得分: 3

你还可以导入一个现有的实现:

import "4d63.com/strrev"

然后:

strrev.Reverse("abåd") // 返回 "dåba"

或者反转一个包含Unicode组合字符的字符串:

strrev.ReverseCombining("abć̝d") // 返回 "d̝́cba"

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

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

英文:

You could also import an existing implementation:

import &quot;4d63.com/strrev&quot;

Then:

strrev.Reverse(&quot;ab&#229;d&quot;) // returns &quot;d&#229;ba&quot;

Or to reverse a string including unicode combining characters:

strrev.ReverseCombining(&quot;abc\u0301\u031dd&quot;) // returns &quot;d\u0301\u031dcba&quot;

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.

答案15

得分: 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

}

英文:

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

package main

import (
  &quot;unicode&quot;
  &quot;regexp&quot;
)

func main() {
    str := &quot;\u0308&quot; + &quot;a\u0308&quot; + &quot;o\u0308&quot; + &quot;u\u0308&quot;
    println(&quot;u\u0308&quot; + &quot;o\u0308&quot; + &quot;a\u0308&quot; + &quot;\u0308&quot; == ReverseGrapheme(str))
    println(&quot;u\u0308&quot; + &quot;o\u0308&quot; + &quot;a\u0308&quot; + &quot;\u0308&quot; == ReverseGrapheme2(str))
}

func ReverseGrapheme(str string) string {

  buf := []rune(&quot;&quot;)
  checked := false
  index := 0
  ret := &quot;&quot; 

    for _, c := range str {

        if !unicode.Is(unicode.M, c) {

            if len(buf) &gt; 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(&quot;&quot;), c)) + ret
        } else {
            buf = append(buf, c)
        }

        index += 1
    }

    return string(buf) + ret
}

func ReverseGrapheme2(str string) string {
    re := regexp.MustCompile(&quot;\\PM\\pM*|.&quot;)
    slice := re.FindAllString(str, -1)
    length := len(slice)
    ret := &quot;&quot;

    for i := 0; i &lt; length; i += 1 {
        ret += slice[length-1-i]
    }

    return ret
}

答案16

得分: 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/issues/detail?id=9055。

英文:

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

package stringutil
import &quot;code.google.com/p/go.text/unicode/norm&quot;

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 &gt;= 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 .

答案17

得分: 2

这是一个确保不是最节省内存的解决方案,但对于一个“简单”的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
}

答案18

得分: 2

以下是翻译好的内容:

以下两种方法比最快的保留组合字符的解决方案运行得更快,尽管这并不意味着在我的基准设置中有什么遗漏。

//输入字符串 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 为反转后的字符串

第二种方法受到这个的启发。

//输入字符串 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 为反转后的字节
英文:

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) &gt; 0 {
    r, size := utf8.DecodeLastRune(bs)
    rs += fmt.Sprintf(&quot;%c&quot;, 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) &gt; 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

答案19

得分: 1

这个答案是2009年的,所以现在可能有更好的解决方案。

看起来有点绕,可能不是很高效,但是说明了如何使用Reader接口从字符串中读取。在处理utf8字符串时,IntVectors也非常适合作为缓冲区。

如果省略'size'部分,并通过Insert将其插入向量,代码会更短,但我猜这样效率会更低,因为每次添加一个新的rune时,整个向量都需要向后推移一个位置。

这个解决方案绝对适用于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 &quot;container/vector&quot;;
import &quot;fmt&quot;;
import &quot;utf8&quot;;
import &quot;bytes&quot;;
import &quot;bufio&quot;;


func
main() {
	toReverse := &quot;Sm&#248;rrebr&#248;d&quot;;
	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 &lt;= size; i++ {
		rune, _, _ := input.ReadRune();
		output.Set(size - i, rune);
	}
	return string(output.Data());
}

答案20

得分: 1

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

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 != &quot;&quot; {
        return Reverse(str[1:]) + str[:1]
	}
	return &quot;&quot;	
}

For Unicode strings it might look like this:

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

答案21

得分: 1

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 &gt;= 0; i-- {
		output.WriteString(string(r[i]))
	}

	return output.String()
}

答案22

得分: 1

简单、简洁和高效

func reverseStr(str string) string {
  strSlice := []rune(str)  //将字符串转换为rune切片
  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)  //将切片转换回字符串
}
英文:

Simple, Sweet and Performant

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

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

答案23

得分: 1

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

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 (
	&quot;fmt&quot;
	&quot;strings&quot;
)

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

func main() {
	fmt.Println(reverse_words(&quot;one two three&quot;))
}

答案24

得分: 1

另一个技巧是使用内置的语言特性,例如 defer

package main

import "fmt"

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

    for _, char := range []rune(name) {
        defer fmt.Printf("%c", char) // <-- 后进先出为您完成所有操作
    }
}
英文:

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

package main

import &quot;fmt&quot;

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

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

答案25

得分: 1

识别Unicode代码点是一回事,但是如何处理字符群集呢?

例如,🏴‍☠️由4个Unicode代码点/符文组成,基于符文对这样的字符串进行反转将产生垃圾。不好。

rivo/uniseg文档中了解更多关于Unicode分段的内容。

这是使用该包进行字符串反转的示例代码:

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, "")
}
英文:

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 &lt; 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, &quot;&quot;)
}

答案26

得分: 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);
}
英文:

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 &gt;= 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);
}

答案27

得分: 0

rune是一种类型,所以要使用它。此外,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 := &quot;the quick brown 狐 jumped over the lazy 犬&quot;
    fmt.Printf(&quot;reverse(%s): [%s]\n&quot;, str, reverse(str))
}

答案28

得分: 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

英文:

try below code:

package main

import &quot;fmt&quot;

func reverse(s string) string {
	chars := []rune(s)
	for i, j := 0, len(chars)-1; i &lt; j; i, j = i+1, j-1 {
		chars[i], chars[j] = chars[j], chars[i]
	}
	return string(chars)
}

func main() {
	fmt.Printf(&quot;%v\n&quot;, reverse(&quot;abcdefg&quot;))
}

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

答案29

得分: 0

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 &gt;= 0; i -- {
            reverseString += string(runeString[i])
        }
        return reverseString
    }

答案30

得分: 0

在golang中,字符串是不可变的对象,与C语言不同,无法原地反转字符串。
在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中,可以使用以下方法,首先将输入转换为字节数组,然后反转字节数组,最后再转换回字符串并返回。这种方法只适用于非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 &lt; 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 &quot;fmt&quot;

func main() {
	s := &quot;test123 4&quot;
	fmt.Println(reverseString(s))
}

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

答案31

得分: 0

包主要

导入 "fmt"

功能 主要() {
变量 str 字符串
fmt.Println("输入一个字符串: ")
fmt.Scanln(&str)

变量 reversed 字符串 = ""
对于 i := len(str) - 1; i >= 0; i-- {
    reversed += string(str[i])
}
fmt.Println(reversed)

}

英文:
package main

import &quot;fmt&quot;

func main() {
	var str string
	fmt.Println(&quot;Enter a string: &quot;)
	fmt.Scanln(&amp;str)

	var reversed string = &quot;&quot;
	for i := len(str) - 1; i &gt;= 0; i-- {
		reversed += string(str[i])
	}
	fmt.Println(reversed)
}

答案32

得分: -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切片。

英文:

Here is yet another solution:

func ReverseStr(s string) string {
    chars := []rune(s)
    rev := make([]rune, 0, len(chars))
    for i := len(chars) - 1; i &gt;= 0; i-- {
        rev = append(rev, chars[i])
    }
    return string(rev)
}

However, yazu's solution above is more elegant since he reverses the []rune slice in place.

答案33

得分: -1

Yet Another Solution (tm) :

包 main 
导入 "fmt"

类型 Runes []rune

函数 (s Runes) Reverse() (cp Runes) {
	l := len(s); cp = make(Runes, l)
	// i <= 1/2 否则会影响奇数长度的字符串
	for i := 0; i <= l/2; i++ { 
		cp[i], cp[l-1-i] = s[l-1-i], s[i] 
	}
	return cp
}

函数 (s Runes) String() string {
	return string(s)
}

函数 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)
}
英文:

Yet Another Solution (tm) :

package main 
import &quot;fmt&quot;

type Runes []rune

func (s Runes) Reverse() (cp Runes) {
	l := len(s); cp = make(Runes, l)
	// i &lt;= 1/2 otherwise it will mess up with odd length strings
	for i := 0; i &lt;= 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 := &quot;The quick brown 狐 jumped over the lazy 犬 +odd&quot; 
	r := Runes(input)
	output := r.Reverse()
	valid := string(output.Reverse()) == input
	fmt.Println(len(r), len(output), r, output.Reverse(), valid)
}

答案34

得分: -1

package reverseString

import "strings"

// ReverseString - 输出给定字符串s的反转字符串
func ReverseString(s string) string {

strLen := len(s)

// 空字符串的反转是空字符串
if strLen == 0 {
	return s
}

// 同上
if strLen == 1 {
	return s
}

// 将s转换为Unicode点
r := []rune(s)

// 最后一个索引
rLen := len(r) - 1

// 新字符串
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 &#250;žasn&#233;!"
r := ReverseString(s)

fmt.Printf("输入: %s\n输出: %s", s, r)

revR := ReverseString(r)

if strings.Compare(s, revR) != 0 {
	t.Errorf("期望: %s\n得到: %s\n", s, revR)
}

}

输出

输入: GO je úžasné!
输出: !énsažú ej OG
PASS
ok github.com/alesr/reverse-string 0.098s

英文:
package reverseString

import &quot;strings&quot;

// 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 &gt;= 0; i-- {
		rev = append(rev, string(r[i]))
	}

	return strings.Join(rev, &quot;&quot;)
}

Test

package reverseString

import (
	&quot;fmt&quot;
	&quot;strings&quot;
	&quot;testing&quot;
)

func TestReverseString(t *testing.T) {

	s := &quot;GO je &#250;žasn&#233;!&quot;
	r := ReverseString(s)

	fmt.Printf(&quot;Input: %s\nOutput: %s&quot;, s, r)

	revR := ReverseString(r)

	if strings.Compare(s, revR) != 0 {
		t.Errorf(&quot;Expecting: %s\n. Got: %s\n&quot;, s, revR)
	}
}

Output

Input: GO je &#250;žasn&#233;!
Output: !&#233;nsaž&#250; ej OG
PASS
ok      github.com/alesr/reverse-string 0.098s

答案35

得分: -1

Defer对于这个很有用,因为它是LIFO - 后进先出的。

英文:
func reverseStr(b string) {
for _, v := range []rune(b) {
	defer fmt.Printf(&quot;%c&quot;, v)

}
 }

Defer is useful for this as it is LIFO - Last in First Out

huangapple
  • 本文由 发表于 2009年11月18日 06:44:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/1752414.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定