当给定包含CJK字符的字符串时,String.length
在字符串中返回错误的字符数,因为它计算字节数。例如:
# String.length "第1";;
- : int = 4
字符串中有两个字符,但String.length
返回4
(字符串中的字节数)。
如何获得包含CJK字符的字符串的实际长度?
如果要计算扩展字形集群(也称为图形字符)的数量,可以使用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标量值写的。
如评论中所述,OCaml对任何特定编码都没有本机支持,因此长度是字节数。
现在,假设您正在使用Utf8编码(这是混合ascii和CJK AFAIK的最简单方法),有几种方法可以计算该大小。
例如,使用非常轻量级的Uutf库[EDIT]作为octachron指出这将以标量值而不是字符返回长度,您应该使用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