mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-07 11:45:31 -05:00
add CCArray.{sorted,sort_indices,sort_ranking} (closes #81)
This commit is contained in:
parent
bc7967054f
commit
2a872907a1
2 changed files with 162 additions and 0 deletions
|
|
@ -51,6 +51,29 @@ module type S = sig
|
|||
val reverse_in_place : 'a t -> unit
|
||||
(** Reverse the array in place *)
|
||||
|
||||
val sorted : ('a -> 'a -> int) -> 'a t -> 'a array
|
||||
(** [sorted cmp a] makes a copy of [a] and sorts it with [cmp].
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val sort_indices : ('a -> 'a -> int) -> 'a t -> int array
|
||||
(** [sort_indices cmp a] returns a new array [b], with the same length as [a],
|
||||
such that [b.(i)] is the index of the [i]-th element in [sort cmp a].
|
||||
In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a].
|
||||
[a] is not modified.
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array
|
||||
(** [sort_ranking cmp a] returns a new array [b], with the same length as [a],
|
||||
such that [b.(i)] is the position in [sorted cmp a] of the [i]-th
|
||||
element of [a].
|
||||
[a] is not modified.
|
||||
|
||||
In other words, [map (fun i -> (sorted cmp a).(i)) (sort_ranking cmp a) = a].
|
||||
|
||||
Without duplicates, we also have
|
||||
[lookup_exn (sorted a) a.(i) = (sorted_ranking a).(i)]
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val find : ('a -> 'b option) -> 'a t -> 'b option
|
||||
(** [find f a] returns [Some y] if there is an element [x] such
|
||||
that [f x = Some y], else it returns [None] *)
|
||||
|
|
@ -260,6 +283,18 @@ let _shuffle _rand_int a i j =
|
|||
let b = Array.copy a in shuffle_with st a; a <> b
|
||||
*)
|
||||
|
||||
let _sort_indices cmp a i j =
|
||||
let len = j-i in
|
||||
let b = Array.init len (fun k->k) in
|
||||
Array.sort (fun k1 k2 -> cmp a.(k1+i) a.(k2+i)) b;
|
||||
b
|
||||
|
||||
let _sorted cmp a i j =
|
||||
let len = j-i in
|
||||
let b = Array.sub a i len in
|
||||
Array.sort cmp b;
|
||||
b
|
||||
|
||||
let _choose a i j st =
|
||||
if i>=j then raise Not_found;
|
||||
a.(i+Random.State.int st (j-i))
|
||||
|
|
@ -366,6 +401,48 @@ let reverse_in_place a =
|
|||
a = [| 6;5;4;3;2;1 |]
|
||||
*)
|
||||
|
||||
let sorted cmp a = _sorted cmp a 0 (Array.length a)
|
||||
|
||||
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
||||
[||] (sorted Pervasives.compare [||])
|
||||
[|0;1;2;3;4|] (sorted Pervasives.compare [|3;2;1;4;0|])
|
||||
*)
|
||||
|
||||
(*$Q
|
||||
Q.(array int) (fun a -> \
|
||||
let b = Array.copy a in \
|
||||
Array.sort Pervasives.compare b; b = sorted Pervasives.compare a)
|
||||
*)
|
||||
|
||||
let sort_indices cmp a = _sort_indices cmp a 0 (Array.length a)
|
||||
|
||||
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
||||
[||] (sort_indices Pervasives.compare [||])
|
||||
[|4;2;1;0;3|] (sort_indices Pervasives.compare [|"d";"c";"b";"e";"a"|])
|
||||
*)
|
||||
|
||||
(*$Q
|
||||
Q.(array printable_string) (fun a -> \
|
||||
let b = sort_indices String.compare a in \
|
||||
sorted String.compare a = Array.map (Array.get a) b)
|
||||
*)
|
||||
|
||||
let sort_ranking cmp a =
|
||||
let cmp_int : int -> int -> int = Pervasives.compare in
|
||||
sort_indices cmp_int (sort_indices cmp a)
|
||||
|
||||
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
||||
[||] (sort_ranking Pervasives.compare [||])
|
||||
[|3;2;1;4;0|] (sort_ranking Pervasives.compare [|"d";"c";"b";"e";"a"|])
|
||||
*)
|
||||
|
||||
(*$Q
|
||||
Q.(array printable_string) (fun a -> \
|
||||
let b = sort_ranking String.compare a in \
|
||||
let a_sorted = sorted String.compare a in \
|
||||
a = Array.map (Array.get a_sorted) b)
|
||||
*)
|
||||
|
||||
let rev a =
|
||||
let b = Array.copy a in
|
||||
reverse_in_place b;
|
||||
|
|
@ -689,6 +766,68 @@ module Sub = struct
|
|||
Sub.reverse_in_place s; a = [| 1; 2; 5; 4; 3; 6 |]
|
||||
*)
|
||||
|
||||
let sorted cmp a = _sorted cmp a.arr a.i a.j
|
||||
|
||||
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
||||
[||] \
|
||||
(let a = 1--6 in let s = Sub.make a 2 ~len:0 in \
|
||||
Sub.sorted Pervasives.compare s)
|
||||
[|2;3;4|] \
|
||||
(let a = [|6;5;4;3;2;1|] in let s = Sub.make a 2 ~len:3 in \
|
||||
Sub.sorted Pervasives.compare s)
|
||||
*)
|
||||
|
||||
(*$Q
|
||||
Q.(array int) (fun a -> \
|
||||
Array.length a > 10 ==> ( Array.length a > 10 && \
|
||||
let s = Sub.make a 5 ~len:5 in \
|
||||
let b = Array.sub a 5 5 in \
|
||||
Array.sort Pervasives.compare b; b = Sub.sorted Pervasives.compare s))
|
||||
*)
|
||||
|
||||
let sort_ranking cmp a =
|
||||
let idx = _sort_indices cmp a.arr a.i a.j in
|
||||
let cmp_int : int -> int -> int = Pervasives.compare in
|
||||
sort_indices cmp_int idx
|
||||
|
||||
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
||||
[||] \
|
||||
(let a = 1--6 in let s = Sub.make a 2 ~len:0 in \
|
||||
Sub.sort_ranking Pervasives.compare s)
|
||||
[|2;1;3;0|] \
|
||||
(let a = [|"d";"c";"b";"e";"a"|] in let s = Sub.make a 1 ~len:4 in \
|
||||
Sub.sort_ranking Pervasives.compare s)
|
||||
*)
|
||||
|
||||
(*$Q
|
||||
Q.(array printable_string) (fun a -> \
|
||||
Array.length a > 10 ==> ( Array.length a > 10 && \
|
||||
let s = Sub.make a 5 ~len:5 in \
|
||||
let b = Sub.sort_indices String.compare s in \
|
||||
Sub.sorted String.compare s = Array.map (Sub.get s) b))
|
||||
*)
|
||||
|
||||
let sort_indices cmp a = _sort_indices cmp a.arr a.i a.j
|
||||
|
||||
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
||||
[||] \
|
||||
(let a = 1--6 in let s = Sub.make a 2 ~len:0 in \
|
||||
Sub.sort_indices Pervasives.compare s)
|
||||
[|3;1;0;2|] \
|
||||
(let a = [|"d";"c";"b";"e";"a"|] in let s = Sub.make a 1 ~len:4 in \
|
||||
Sub.sort_indices Pervasives.compare s)
|
||||
*)
|
||||
|
||||
(*$Q
|
||||
Q.(array printable_string) (fun a -> \
|
||||
Array.length a > 10 ==> ( Array.length a > 10 && \
|
||||
let s = Sub.make a 5 ~len:5 in \
|
||||
let b = Sub.sort_ranking String.compare s in \
|
||||
let a_sorted = Sub.sorted String.compare s in \
|
||||
Sub.copy s = Array.map (Array.get a_sorted) b))
|
||||
*)
|
||||
|
||||
|
||||
let find f a = _find (fun _ -> f) a.arr a.i a.j
|
||||
|
||||
let findi f a = _find (fun i -> f (i-a.i)) a.arr a.i a.j
|
||||
|
|
|
|||
|
|
@ -53,6 +53,29 @@ module type S = sig
|
|||
val reverse_in_place : 'a t -> unit
|
||||
(** Reverse the array in place *)
|
||||
|
||||
val sorted : ('a -> 'a -> int) -> 'a t -> 'a array
|
||||
(** [sorted cmp a] makes a copy of [a] and sorts it with [cmp].
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val sort_indices : ('a -> 'a -> int) -> 'a t -> int array
|
||||
(** [sort_indices cmp a] returns a new array [b], with the same length as [a],
|
||||
such that [b.(i)] is the index of the [i]-th element in [sort cmp a].
|
||||
In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a].
|
||||
[a] is not modified.
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array
|
||||
(** [sort_ranking cmp a] returns a new array [b], with the same length as [a],
|
||||
such that [b.(i)] is the position in [sorted cmp a] of the [i]-th
|
||||
element of [a].
|
||||
[a] is not modified.
|
||||
|
||||
In other words, [map (fun i -> (sorted cmp a).(i)) (sort_ranking cmp a) = a].
|
||||
|
||||
Without duplicates, we also have
|
||||
[lookup_exn a.(i) (sorted a) = (sorted_ranking a).(i)]
|
||||
@since NEXT_RELEASE *)
|
||||
|
||||
val find : ('a -> 'b option) -> 'a t -> 'b option
|
||||
(** [find f a] returns [Some y] if there is an element [x] such
|
||||
that [f x = Some y], else it returns [None] *)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue