Ви можете спробувати RuneCountInString
з пакету utf8.
повертає кількість рун у p
що, як проілюстровано у цьому сценарії : довжина "Світу" може бути 6 (коли написано китайською мовою: "世界"), але його кількість рун - 2:
package main
import "fmt"
import "unicode/utf8"
func main() {
fmt.Println("Hello, 世界", len("世界"), utf8.RuneCountInString("世界"))
}
Phrozen додає в коментарях :
Насправді ви можете обійтися len()
над рунами, просто ввівши кастинг.
len([]rune("世界"))
надрукує 2
. В літі в Go 1.3.
А з CL 108985 (травень 2018 року, для Go 1.11) len([]rune(string))
тепер оптимізовано. (Виправлення випуску 24923 )
Компілятор визначає len([]rune(string))
шаблон автоматично і замінює його на r: = range s call.
Додає нову функцію виконання для підрахунку рун у рядку. Змінює компілятор для виявлення шаблону len([]rune(string))
та замінює його новою функцією виконання підрахунку рун.
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)
Стефан Штайгер вказує на допис у блозі " Нормалізація тексту в режимі "
Що таке персонаж?
Як згадувалося в публікації в блозі рядків , символи можуть охоплювати кілька рун .
Наприклад, ' e
' і '◌́◌́' (гострий "\ u0301") можуть поєднуватися, утворюючи "é" (" e\u0301
" в NFD). Разом ці дві руни - один символ .
Визначення символу може змінюватися залежно від програми.
Для нормалізації ми визначимо це як:
- послідовність рун, яка починається зі стартера,
- руна, яка не змінює і не поєднує назад з будь-якою іншою руною,
- з наступною можливою порожньою послідовністю нестартерів, тобто рун, які це роблять (як правило, наголоси).
Алгоритм нормалізації обробляє один символ одночасно.
Використовуючи цей пакет та його Iter
тип , фактична кількість "символів" буде:
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)
}
Тут для цього використовується форма нормалізації Unicode NFKD "Розбір сумісності"
Oliver «s відповідь вказує на UNICODE TEXT СЕГМЕНТАЦІЇ як єдиний спосіб надійно визначити межі по замовчуванням між деякими значними елементами тексту: призначені для користувача сприймаються символів, слів і фраз.
Для цього вам потрібна зовнішня бібліотека на зразок rivo / uniseg , яка робить сегментацію тексту Unicode .
Це насправді буде рахувати " кластер графеми ", де кілька точок коду можуть бути об'єднані в один сприйнятий користувачем символ.
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]
}
Дві графеми, хоча є три руни (кодові точки Unicode).
Ви можете побачити інші приклади в " Як маніпулювати рядками в GO, щоб повернути їх назад? "
👩🏾🦰 одне - це одна графема, але, від унікоду до перетворювача кодів , 4 руни: