去寻找行数的最快方法?

时间:2017-11-11 16:24:30

标签: string performance go

我现在正在使用的内容:

numlines := strings.Count(editor.Text(), "\n")
fmt.Print(strconv.Itoa(numlines))
message.SetText(strconv.Itoa(numlines))

每当更新文本框时都会运行此选项。最喜欢这样做的方式是什么?

2 个答案:

答案 0 :(得分:4)

这很好。但是不要忘记,如果最后一个字符不是换行符,则必须在出现次数上加1,因为这将是行数(最后一行可能不以换行符结尾)。

我们可能会想到,因为您计算的子字符串只是一个字符(单个rune),我们可以创建一个自定义解决方案,仅计算此单个字符的出现次数(而不是计算子字符串的数量) )。它可能看起来像这样:

func countRune(s string, r rune) int {
    count := 0
    for _, c := range s {
        if c == r {
            count++
        }
    }
    return count
}

for range值上的string会在其rune上进行迭代。)

测试它(在Go Playground上试试):

fmt.Println(countRune("asdf\nasdf\nasdf\n", '\n')) // Prints 3

实际上,这不会更快地计算换行符,因为它是UTF-8编码中的单个byte,并且strings.Count()已经优化用于计算子串的长度为子串的子串1:

// Count counts the number of non-overlapping instances of substr in s.
// If substr is an empty string, Count returns 1 + the number of Unicode code points in s.
func Count(s, substr string) int {
    if len(substr) == 1 && cpu.X86.HasPOPCNT {
        return countByte(s, byte(substr[0]))
    }
    return countGeneric(s, substr)
}

func countByte(s string, c byte) int // ../runtime/asm_amd64.s

如果您可以访问编辑器的“内部”字节或符文数组,那么可以改善此操作(计数行)的性能是什么,因此您不必调用其Text()方法,创建并返回其内容的副本。

答案 1 :(得分:1)

当您询问有关最快方式的问题时,您应该使用Go testing软件包基准测试工具进行衡量。

例如,使用strings.Count并在for range上使用string循环计算lorem ipsum中的行数,并衡量从{转换的任何额外费用{1}}切片到byte。您可以通过计算string切片中的行数来避免任何byte切片到string开销。

byte

$ gotest lines_test.go -bench=. data: /home/peter/shakespeare.pg100.txt 5589889 BenchmarkStringCount-4 30000000 57.3 ns/op 0 B/op 0 allocs/op BenchmarkStringByRune-4 3000000 563 ns/op 0 B/op 0 allocs/op BenchmarkBytesToString-4 10000000 173 ns/op 480 B/op 1 allocs/op BenchmarkBytesCount-4 20000000 61.2 ns/op 0 B/op 0 allocs/op

lines_test.go