mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
add CCString.compare_natural (closes #146)
This commit is contained in:
parent
d076afc405
commit
acb286d8e8
2 changed files with 61 additions and 0 deletions
|
|
@ -414,6 +414,44 @@ let compare_versions a b =
|
||||||
in
|
in
|
||||||
cmp_rec (Split.gen_cpy ~by:"." a) (Split.gen_cpy ~by:"." b)
|
cmp_rec (Split.gen_cpy ~by:"." a) (Split.gen_cpy ~by:"." b)
|
||||||
|
|
||||||
|
type nat_chunk =
|
||||||
|
| NC_char of char
|
||||||
|
| NC_int of int
|
||||||
|
|
||||||
|
let compare_natural a b =
|
||||||
|
(* stream of chunks *)
|
||||||
|
let chunks s : unit -> nat_chunk option =
|
||||||
|
let i = ref 0 in
|
||||||
|
let rec next () =
|
||||||
|
if !i = length s then None
|
||||||
|
else match String.get s !i with
|
||||||
|
| '0'..'9' as c -> incr i; read_int (Char.code c - Char.code '0')
|
||||||
|
| c -> incr i; Some (NC_char c)
|
||||||
|
and read_int n =
|
||||||
|
if !i = length s then Some (NC_int n)
|
||||||
|
else match String.get s !i with
|
||||||
|
| '0'..'9' as c -> incr i; read_int (10 * n + Char.code c - Char.code '0')
|
||||||
|
| _ -> Some (NC_int n)
|
||||||
|
in
|
||||||
|
next
|
||||||
|
in
|
||||||
|
let rec cmp_rec a b = match a(), b() with
|
||||||
|
| None, None -> 0
|
||||||
|
| Some _, None -> 1
|
||||||
|
| None, Some _ -> -1
|
||||||
|
| Some x, Some y ->
|
||||||
|
match x, y with
|
||||||
|
| NC_char x, NC_char y ->
|
||||||
|
let c = Char.compare x y in
|
||||||
|
if c<>0 then c else cmp_rec a b
|
||||||
|
| NC_int _, NC_char _ -> 1
|
||||||
|
| NC_char _, NC_int _ -> -1
|
||||||
|
| NC_int x, NC_int y ->
|
||||||
|
let c = Pervasives.compare x y in
|
||||||
|
if c<>0 then c else cmp_rec a b
|
||||||
|
in
|
||||||
|
cmp_rec (chunks a) (chunks b)
|
||||||
|
|
||||||
let edit_distance s1 s2 =
|
let edit_distance s1 s2 =
|
||||||
if length s1 = 0
|
if length s1 = 0
|
||||||
then length s2
|
then length s2
|
||||||
|
|
|
||||||
|
|
@ -578,6 +578,29 @@ val compare_versions : string -> string -> int
|
||||||
CCOrd.equiv (compare_versions a b) (CCOrd.opp compare_versions b a))
|
CCOrd.equiv (compare_versions a b) (CCOrd.opp compare_versions b a))
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
val compare_natural : string -> string -> int
|
||||||
|
(** Natural Sort Order, comparing chunks of digits as natural numbers.
|
||||||
|
https://en.wikipedia.org/wiki/Natural_sort_order
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
|
(*$T
|
||||||
|
compare_natural "foo1" "foo2" < 0
|
||||||
|
compare_natural "foo11" "foo2" > 0
|
||||||
|
compare_natural "foo11" "foo11" = 0
|
||||||
|
compare_natural "foo011" "foo11" = 0
|
||||||
|
compare_natural "foo1a" "foo1b" < 0
|
||||||
|
compare_natural "foo1a1" "foo1a2" < 0
|
||||||
|
compare_natural "foo1a17" "foo1a2" > 0
|
||||||
|
*)
|
||||||
|
|
||||||
|
(*Q
|
||||||
|
(Q.pair printable_string printable_string) (fun (a,b) -> \
|
||||||
|
CCOrd.opp (compare_natural a b) = compare_natural b a)
|
||||||
|
(Q.printable_string) (fun a -> compare_natural a a = 0)
|
||||||
|
(Q.triple printable_string printable_string printable_string) (fun (a,b,c) -> \
|
||||||
|
if compare_natural a b < 0 && compare_natural b c < 0 \
|
||||||
|
then compare_natural a c < 0 else Q.assume_fail())
|
||||||
|
*)
|
||||||
|
|
||||||
val edit_distance : string -> string -> int
|
val edit_distance : string -> string -> int
|
||||||
(** Edition distance between two strings. This satisfies the classical
|
(** Edition distance between two strings. This satisfies the classical
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue