通过在golang中使用for循环来反转字符串效率低下?

时间:2019-06-05 19:25:55

标签: go

我像这样的Golang做到了

func reverseStr(str string) string {
    var reversed string

    for i := len(str) - 1; i >= 0; i-- {
        reversed += string(str[i])
    }

    return reversed
}

我是一个初学者,暂时不能做得更好,但是我仍在学习。我想知道我的方法是否比在网上看到的使用符文的方法效率低:

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

2 个答案:

答案 0 :(得分:3)

  

我想知道我的方法是否比在线看到的使用符文的方法效率低

与符文或for循环无关。您的方法一遍又一遍地构建和重建以及重建字符串。另一个则通过简单地交换字符来就地反转字符串。而且,只有更大的琴弦,这种区别才会变得更糟。

package main

import "testing"

func reverseConcat(str string) string {
    var reversed string

    for i := len(str) - 1; i >= 0; i-- {
        reversed += string(str[i])
    }

    return reversed
}

func reverseSwapRunes(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 BenchmarkConcatSmall(b *testing.B) {
    for i := 0; i < b.N; i++ {
        reverseConcat("hello world")
    }
}

func BenchmarkSwapRunesSmall(b *testing.B) {
    for i := 0; i < b.N; i++ {
        reverseSwapRunes("hello world")
    }
}

func BenchmarkConcatLarger(b *testing.B) {
    for i := 0; i < b.N; i++ {
        reverseConcat("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
    }
}

func BenchmarkSwapRunesLarger(b *testing.B) {
    for i := 0; i < b.N; i++ {
        reverseSwapRunes("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
    }
}

结果

$ go test -bench . -benchmem
goos: linux
goarch: amd64
BenchmarkConcatSmall-8           5000000           329 ns/op          80 B/op         10 allocs/op
BenchmarkSwapRunesSmall-8       20000000           117 ns/op          16 B/op          1 allocs/op
BenchmarkConcatLarger-8            30000         44877 ns/op      172833 B/op        573 allocs/op
BenchmarkSwapRunesLarger-8        300000          5353 ns/op        2944 B/op          2 allocs/op

答案 1 :(得分:0)

您的第一个解决方案仅适用于ASCII字符,因为len(str)为您提供以字节为单位的len,而str [i]也返回字节。一旦处理Unicode,它就会失败,因为一个Unicode(符文)可以有多个字节。

type byte = uint8
type rune = int32

因此您的第二个解决方案将适用于任何类型的字符串字符。

另一个例子是使用strings.Builder

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()
}
在我的测试中,

的性能与数组替换(第二个示例)几乎相同-比字符串连接快3倍。

BenchmarkReverseStrConcat-8    1000000  1571 ns/op  176 B/op    29 allocs/op     
BenchmarkReverseStrBuilder-8   3000000  499 ns/op   56 B/op 6 allocs/op