numlines := strings.Count(editor.Text(), "\n")
fmt.Print(strconv.Itoa(numlines))
message.SetText(strconv.Itoa(numlines))
テキストボックスが更新されるたびにこれが実行されます。これを行うにはどういった方法がありますか?
numlines := strings.Count(editor.Text(), "\n")
fmt.Print(strconv.Itoa(numlines))
message.SetText(strconv.Itoa(numlines))
テキストボックスが更新されるたびにこれが実行されます。これを行うにはどういった方法がありますか?
これは完璧です。しかし、最後の文字が改行文字でない場合は、出現回数に1を加えなければならないことを忘れないでください。行数(最後の行は改行で終わらないかもしれません)。
カウントしている部分文字列が1文字(単一のrune
)であるため、(文字列をカウントする代わりに)この1文字の出現のみをカウントするカスタムソリューションを作成することができます。
func countRune(s string, r rune) int {
count := 0
for _, c := range s {
if c == r {
count++
}
}
return count
}
(そのrune
秒以上string
値を反復処理上for range
。)
そして、それをテストする(Go Playground上でそれを試してみてください):
でfmt.Println(countRune("asdf\nasdf\nasdf\n", '\n')) // Prints 3
それはこのように見えるかもしれませんこれは、UTF-8エンコーディングでbyte
という単一のものであり、部分文字列の長さが部分文字列の数になるように既に最適化されているので、改行文字をより高速に数えることはできません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()
メソッドを呼び出す必要がありませんこれは、コンテンツのコピーを作成して返します。
最速の方法について質問するときは、Go testing
パッケージベンチマーク機能を使用して測定する必要があります。例えば
、strings.Count
を用いてstring
上for range
ループを使用lorem ipsumの行数をカウントし、string
にbyte
スライスからの変換の追加のコストを測定します。 byte
スライス内の行数を数えることによって、byte
スライスからstring
オーバヘッドまでを避けることができます。
$ 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
:
package main
import (
"bytes"
"strconv"
"strings"
"testing"
)
func linesStringCount(s string) string {
n := strings.Count(s, "\n")
if len(s) > 0 && !strings.HasSuffix(s, "\n") {
n++
}
return strconv.Itoa(n)
}
func linesStringByRune(s string) string {
n := 0
for _, r := range s {
if r == '\n' {
n++
}
}
if len(s) > 0 && !strings.HasSuffix(s, "\n") {
n++
}
return strconv.Itoa(n)
}
func linesBytesCount(s []byte) string {
nl := []byte{'\n'}
n := bytes.Count(s, nl)
if len(s) > 0 && !bytes.HasSuffix(s, nl) {
n++
}
return strconv.Itoa(n)
}
var data = []byte(`Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.`)
func BenchmarkStringCount(b *testing.B) {
text := string(data)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = linesStringCount(text)
}
}
func BenchmarkStringByRune(b *testing.B) {
text := string(data)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = linesStringByRune(text)
}
}
func BenchmarkBytesToText(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = string(data)
}
}
func BenchmarkBytesCount(b *testing.B) {
text := data
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = linesBytesCount(text)
}
}