Длина строки, содержащей символы CJK - PullRequest
2 голосов
/ 09 марта 2019

Если задана строка, содержащая символы CJK, String.length возвращает неверное количество символов в строке, поскольку она подсчитывает количество байтов.Например:

# String.length "第1";;
- : int = 4

В строке два символа, но String.length возвращает 4 (это количество байтов в строке).

Как получитьреальная длина строки, содержащей символы CJK?

Ответы [ 2 ]

3 голосов
/ 09 марта 2019

Если вы хотите посчитать количество кластеров расширенных графем (или графических символов), вы можете использовать Uuseg для сегментации:

let len = Uuseg_string.fold_utf_8 `Grapheme_cluster (fun x _ -> x + 1) 0
;; len "春"

1

, который имеет преимущество в том, что он все еще точен в присутствии непредставленных символов, таких как разложенный джамо по-корейски:

 ;; len "\u{1112}\u{1161}\u{11AB}"

1

, который является правильным результатом, так как предыдущие строки должны отображаться как , даже если он записан с 3 скалярными значениями Юникода.

0 голосов
/ 09 марта 2019

Как указано в комментариях, OCaml не имеет встроенной поддержки какой-либо конкретной кодировки, поэтому длина равна числу байтов.

Теперь, если вы используете кодировку Utf8 (это самый простой способ смешать ascii и CJK AFAIK), есть несколько способов вычислить этот размер.

В качестве примера, используя очень легковесную библиотеку Uutf [EDIT], как указывал октахрон, это возвращает длину в скалярных значениях, а не в символах, вы должны использовать ответ октахрона.

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
...