Bạn có thể thử RuneCountInString
từ gói utf8.
trả về số lượng rune trong p
rằng, như được minh họa trong kịch bản này : độ dài của "Thế giới" có thể là 6 (khi được viết bằng tiếng Trung: ""), nhưng số lượng rune của nó là 2:
package main
import "fmt"
import "unicode/utf8"
func main() {
fmt.Println("Hello, 世界", len("世界"), utf8.RuneCountInString("世界"))
}
Ph Frozen cho biết thêm trong các ý kiến :
Trên thực tế bạn có thể làm len()
hơn runes chỉ bằng cách gõ.
len([]rune("世界"))
sẽ in 2
. Tại các nhánh trong Go 1.3.
Và với CL 108985 (tháng 5 năm 2018, cho Go 1.11), len([]rune(string))
giờ đã được tối ưu hóa. ( Khắc phục sự cố 24923 )
Trình biên dịch len([]rune(string))
tự động phát hiện mẫu và thay thế nó bằng lệnh gọi r: = Range s.
Thêm một chức năng thời gian chạy mới để đếm rune trong một chuỗi. Sửa đổi trình biên dịch để phát hiện mẫu len([]rune(string))
và thay thế nó bằng hàm rune đếm thời gian chạy mới.
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 chỉ vào bài đăng trên blog "Bình thường hóa văn bản trong Go "
Một nhân vật là gì?
Như đã đề cập trong bài viết trên blog chuỗi , các ký tự có thể trải rộng trên nhiều rune .
Ví dụ: một ' e
' và '◌́◌́' (cấp tính "\ u0301") có thể kết hợp để tạo thành 'é' (" e\u0301
" trong NFD). Hai rune cùng nhau là một nhân vật .
Định nghĩa của một nhân vật có thể thay đổi tùy thuộc vào ứng dụng.
Để chuẩn hóa, chúng tôi sẽ định nghĩa nó là:
- một chuỗi các rune bắt đầu với một khởi đầu,
- một rune không sửa đổi hoặc kết hợp ngược với bất kỳ rune khác,
- theo sau là chuỗi không có khả năng khởi động trống, nghĩa là rune làm (thường là dấu).
Thuật toán chuẩn hóa xử lý một ký tự tại một thời điểm.
Sử dụng gói đó và Iter
loại của nó , số "ký tự" thực tế sẽ là:
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)
}
Ở đây, điều này sử dụng biểu mẫu Chuẩn hóa Unicode "Phân tích tương thích"
Câu trả lời của Oliver chỉ ra GIỚI THIỆU VĂN BẢN UNICODE là cách duy nhất để xác định đáng tin cậy ranh giới mặc định giữa các yếu tố văn bản quan trọng nhất định: ký tự, từ và câu nhận thức của người dùng.
Để làm được điều đó, bạn cần một thư viện bên ngoài như rivo / uniseg , phân đoạn văn bản Unicode .
Điều đó thực sự sẽ tính " cụm grapheme ", trong đó nhiều điểm mã có thể được kết hợp thành một ký tự do người dùng cảm nhận.
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]
}
Hai biểu đồ, mặc dù có ba rune (điểm mã Unicode).
Bạn có thể xem các ví dụ khác trong " Cách thao tác chuỗi trong GO để đảo ngược chúng? "
Một mình là một grapheme, nhưng, từ unicode sang bộ chuyển đổi điểm mã , 4 rune: