Możesz spróbować RuneCountInString
z pakietu utf8.
zwraca liczbę run w p
że, jak zilustrowano w tym skrypcie : długość „Świata” może wynosić 6 (po chińsku: „世界”), ale liczba jego run to 2:
package main
import "fmt"
import "unicode/utf8"
func main() {
fmt.Println("Hello, 世界", len("世界"), utf8.RuneCountInString("世界"))
}
Phrozen dodaje w komentarzach :
Właściwie możesz zrobić len()
nad runami, po prostu rzucając typ.
len([]rune("世界"))
wydrukuje 2
. Co najmniej w Go 1.3.
A z CL 108985 (maj 2018, dla Go 1.11), len([]rune(string))
jest teraz zoptymalizowany. (Rozwiązuje problem 24923 )
Kompilator len([]rune(string))
automatycznie wykrywa wzorzec i zastępuje go wywołaniem for r: = range s.
Dodaje nową funkcję wykonawczą do liczenia run w ciągu. Modyfikuje kompilator, aby wykrywał wzorzec len([]rune(string))
i zastępuje go nową funkcją zliczania run.
RuneCount/lenruneslice/ASCII 27.8ns ± 2% 14.5ns ± 3% -47.70% (p=0.000 n=10+10)
RuneCount/lenruneslice/Japanese 126ns ± 2% 60ns ± 2% -52.03% (p=0.000 n=10+10)
RuneCount/lenruneslice/MixedLength 104ns ± 2% 50ns ± 1% -51.71% (p=0.000 n=10+9)
Stefan Steiger wskazuje na post na blogu „ Normalizacja tekstu w Go ”
Co to jest postać?
Jak wspomniano w poście na blogu dotyczącym ciągów znaków , znaki mogą obejmować wiele run .
Na przykład ' e
' i '◌́◌́' (ostry "\ u0301") mogą łączyć się tworząc 'é' (" e\u0301
" w NFD). Te dwie runy razem stanowią jedną postać .
Definicja postaci może się różnić w zależności od aplikacji.
Dla normalizacji zdefiniujemy to jako:
- sekwencja run rozpoczynająca się od startera,
- runa, która nie modyfikuje ani nie łączy się wstecz z żadną inną runą,
- po którym może następować prawdopodobnie pusta sekwencja nieuruchomionych znaków, czyli run, które to robią (zazwyczaj akcenty).
Algorytm normalizacji przetwarza jednocześnie jeden znak.
Używając tego pakietu i jego Iter
typu , rzeczywista liczba „znaków” byłaby następująca:
package main
import "fmt"
import "golang.org/x/text/unicode/norm"
func main() {
var ia norm.Iter
ia.InitString(norm.NFKD, "école")
nc := 0
for !ia.Done() {
nc = nc + 1
ia.Next()
}
fmt.Printf("Number of chars: %d\n", nc)
}
Tutaj używa się formularza normalizacji Unicode NFKD „Dekompozycja zgodności”
Oliver „s odpowiedź wskazuje na UNICODE TEKSTU SEGMENTACJI jako jedyny sposób, aby niezawodnie wyznaczania granic pomiędzy niektórymi domyślne istotnych elementów tekstowych: odczuwanego przez użytkownika znaków, wyrazów i zdań.
W tym celu potrzebujesz zewnętrznej biblioteki, takiej jak rivo / uniseg , która obsługuje segmentację tekstu Unicode .
W rzeczywistości liczy się „ klaster grafemów ”, w którym wiele punktów kodowych można połączyć w jeden znak postrzegany przez użytkownika.
package uniseg
import (
"fmt"
"github.com/rivo/uniseg"
)
func main() {
gr := uniseg.NewGraphemes("👍🏼!")
for gr.Next() {
fmt.Printf("%x ", gr.Runes())
}
// Output: [1f44d 1f3fc] [21]
}
Dwa grafemy, mimo że są trzy runy (punkty kodowe Unicode).
Możesz zobaczyć inne przykłady w „ Jak manipulować ciągami znaków w GO, aby je odwrócić? ”
👩🏾🦰 sam to jeden grafem, ale od konwertera Unicode do punktów kodowych 4 runy: