我现在正在使用的内容:
numlines := strings.Count(editor.Text(), "\n")
fmt.Print(strconv.Itoa(numlines))
message.SetText(strconv.Itoa(numlines))
每当更新文本框时都会运行此选项。最喜欢这样做的方式是什么?
答案 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