包含 CJK 字符的字符串长度
Length of string that contains CJK characters
当给定一个包含 CJK 字符的字符串时,String.length
returns 字符串中的字符数错误,因为它计算的是字节数。例如:
# String.length "第1";;
- : int = 4
字符串中有两个字符,但是String.length
returns4
(也就是字符串的字节数)
如何获取包含 CJK 字符的字符串的实际长度?
如评论中所述,OCaml 没有对任何特定编码的本机支持,因此长度是字节数。
现在,假设您使用的是 Utf8 编码(这是混合 ascii 和 CJK AFAIK 的最简单方法),有几种方法可以计算该大小。
例如,使用非常轻量级的 Uutf 库 [EDIT] as octachron 指出了这个 returns 标量值而不是字符的长度,你应该使用 octachron 的答案。
let utf8_length s = (* returns the number of unicode scalar values *)
let decoder = Uutf.decoder ~encoding:`UTF_8 (`String s) in
let rec loop () = match Uutf.decode decoder with | `End -> () | _ -> loop () in
loop ();
Uutf.decoder_count decoder
如果要计算扩展字素簇(又名图形字符)的数量,可以使用Uuseg
进行分割:
let len = Uuseg_string.fold_utf_8 `Grapheme_cluster (fun x _ -> x + 1) 0
;; len "春"
1
它的优点是在存在非预组合字符(如韩语中分解的 jamo)时仍然准确:
;; len "\u{1112}\u{1161}\u{11AB}"
1
这是正确的结果,因为前面的字符串应该显示为 한
,即使它是用 3 个 unicode 标量值编写的。
当给定一个包含 CJK 字符的字符串时,String.length
returns 字符串中的字符数错误,因为它计算的是字节数。例如:
# String.length "第1";;
- : int = 4
字符串中有两个字符,但是String.length
returns4
(也就是字符串的字节数)
如何获取包含 CJK 字符的字符串的实际长度?
如评论中所述,OCaml 没有对任何特定编码的本机支持,因此长度是字节数。
现在,假设您使用的是 Utf8 编码(这是混合 ascii 和 CJK AFAIK 的最简单方法),有几种方法可以计算该大小。
例如,使用非常轻量级的 Uutf 库 [EDIT] as octachron 指出了这个 returns 标量值而不是字符的长度,你应该使用 octachron 的答案。
let utf8_length s = (* returns the number of unicode scalar values *)
let decoder = Uutf.decoder ~encoding:`UTF_8 (`String s) in
let rec loop () = match Uutf.decode decoder with | `End -> () | _ -> loop () in
loop ();
Uutf.decoder_count decoder
如果要计算扩展字素簇(又名图形字符)的数量,可以使用Uuseg
进行分割:
let len = Uuseg_string.fold_utf_8 `Grapheme_cluster (fun x _ -> x + 1) 0
;; len "春"
1
它的优点是在存在非预组合字符(如韩语中分解的 jamo)时仍然准确:
;; len "\u{1112}\u{1161}\u{11AB}"
1
这是正确的结果,因为前面的字符串应该显示为 한
,即使它是用 3 个 unicode 标量值编写的。