mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
feat(list): add sorted_diff_uniq
Also fixed documentation
This commit is contained in:
parent
80e403c969
commit
8d532f9a00
3 changed files with 70 additions and 8 deletions
|
|
@ -958,6 +958,40 @@ let sorted_merge_uniq ~cmp l1 l2 =
|
||||||
uniq_succ ~eq:CCInt.equal l3 = l3)
|
uniq_succ ~eq:CCInt.equal l3 = l3)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
let sorted_diff_uniq ~cmp l1 l2 =
|
||||||
|
let push ~cmp acc x = match acc with
|
||||||
|
| [] -> [x]
|
||||||
|
| y :: _ when cmp x y > 0 -> x :: acc
|
||||||
|
| _ -> acc (* duplicate, do not yield *)
|
||||||
|
in
|
||||||
|
let rec recurse ~cmp acc l1 l2 = match l1,l2 with
|
||||||
|
| [], _ -> List.rev acc
|
||||||
|
| l, [] ->
|
||||||
|
let acc = List.fold_left (push ~cmp) acc l in
|
||||||
|
List.rev acc
|
||||||
|
| x1::l1', x2::l2' ->
|
||||||
|
let c = cmp x1 x2 in
|
||||||
|
if c < 0 then recurse ~cmp (push ~cmp acc x1) l1' l2
|
||||||
|
else if c > 0 then recurse ~cmp acc l1 l2'
|
||||||
|
else recurse ~cmp acc l1' l2'
|
||||||
|
in
|
||||||
|
recurse ~cmp [] l1 l2
|
||||||
|
|
||||||
|
(*$T
|
||||||
|
sorted_diff_uniq ~cmp:CCInt.compare [1; 1; 1; 2; 2; 3; 5; 8; 8; 8] [1; 2; 2; 2; 2; 8; 13; 13; 13] = [1;3;5;8]
|
||||||
|
*)
|
||||||
|
|
||||||
|
(*$Q
|
||||||
|
Q.(pair (list small_int) (list small_int)) (fun (l1, l2) -> \
|
||||||
|
let l1 = List.sort CCInt.compare l1 in \
|
||||||
|
let l2 = List.sort CCInt.compare l2 in \
|
||||||
|
is_sorted ~cmp:CCInt.compare (sorted_diff_uniq ~cmp:CCInt.compare l1 l2))
|
||||||
|
Q.(pair (list small_int) (list small_int)) (fun (l1, l2) -> \
|
||||||
|
let l1 = List.sort CCInt.compare l1 in \
|
||||||
|
let l2 = List.sort CCInt.compare l2 in \
|
||||||
|
sorted_diff_uniq ~cmp:CCInt.compare l1 l2 = uniq_succ ~eq:CCInt.equal (sorted_diff ~cmp:CCInt.compare l1 l2))
|
||||||
|
*)
|
||||||
|
|
||||||
let take n l =
|
let take n l =
|
||||||
let rec direct i n l = match l with
|
let rec direct i n l = match l with
|
||||||
| [] -> []
|
| [] -> []
|
||||||
|
|
|
||||||
|
|
@ -504,8 +504,10 @@ val sorted_merge : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
||||||
val sorted_diff : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
val sorted_diff : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
||||||
(** [sorted_diff ~cmp l1 l2] returns the elements in [l1] that are not in [l2].
|
(** [sorted_diff ~cmp l1 l2] returns the elements in [l1] that are not in [l2].
|
||||||
Both lists are assumed to be sorted with respect to [cmp] and
|
Both lists are assumed to be sorted with respect to [cmp] and
|
||||||
duplicate elements are treated individually. It is the left inverse of
|
duplicate elements in the input lists are treated individually;
|
||||||
[sorted_merge]; that is, [sorted_diff ~cmp (sorted_merge ~cmp l1 l2) l2]
|
for example, [sorted_diff ~cmp [1;1;1;2;2;3] [1;2;2]] would be [[1;1;3]].
|
||||||
|
It is the left inverse of [sorted_merge]; that is,
|
||||||
|
[sorted_diff ~cmp (sorted_merge ~cmp l1 l2) l2]
|
||||||
is always equal to [l1] for sorted lists [l1] and [l2].
|
is always equal to [l1] for sorted lists [l1] and [l2].
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
|
|
@ -518,6 +520,16 @@ val sorted_merge_uniq : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
||||||
removes duplicates.
|
removes duplicates.
|
||||||
@since 0.10 *)
|
@since 0.10 *)
|
||||||
|
|
||||||
|
val sorted_diff_uniq : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
||||||
|
(** [sorted_diff_uniq ~cmp l1 l2] collects the elements in [l1] that are not in [l2]
|
||||||
|
and then remove duplicates.
|
||||||
|
Both lists are assumed to be sorted with respect to [cmp] and
|
||||||
|
duplicate elements in the input lists are treated individually;
|
||||||
|
for example, [sorted_diff_uniq ~cmp [1;1;1;2;2] [1;2;2;2]] would be [[1]].
|
||||||
|
[sorted_diff_uniq ~cmp l1 l2] and [uniq_succ ~eq (sorted_diff ~cmp l1 l2)]
|
||||||
|
always give the same result for sorted [l1] and [l2] and compatible [cmp] and [eq].
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val is_sorted : cmp:('a -> 'a -> int) -> 'a list -> bool
|
val is_sorted : cmp:('a -> 'a -> int) -> 'a list -> bool
|
||||||
(** [is_sorted ~cmp l] returns [true] iff [l] is sorted (according to given order).
|
(** [is_sorted ~cmp l] returns [true] iff [l] is sorted (according to given order).
|
||||||
@param cmp the comparison function.
|
@param cmp the comparison function.
|
||||||
|
|
@ -535,8 +547,10 @@ val sorted_insert : cmp:('a -> 'a -> int) -> ?uniq:bool -> 'a -> 'a list -> 'a l
|
||||||
@since 0.17 *)
|
@since 0.17 *)
|
||||||
|
|
||||||
val sorted_remove : cmp:('a -> 'a -> int) -> ?all:bool -> 'a -> 'a list -> 'a list
|
val sorted_remove : cmp:('a -> 'a -> int) -> ?all:bool -> 'a -> 'a list -> 'a list
|
||||||
(** [sorted_insert ~cmp ~key l] removes [key] from a sorted list [l] such that
|
(** [sorted_remove ~cmp x l] removes [x] from a sorted list [l] such that
|
||||||
the return value is sorted too.
|
the return value is sorted too. By default, it is the left inverse of
|
||||||
|
[sorted_insert]; that is, [sorted_remove ~cmp x (sorted_insert ~cmp x l)]
|
||||||
|
is equal to [l] for any sorted list [l].
|
||||||
@param all if true then all occurrences of [x] will be removed. Otherwise, only the first
|
@param all if true then all occurrences of [x] will be removed. Otherwise, only the first
|
||||||
[x] will be removed (if any). Default [false] (only the first will be removed).
|
[x] will be removed (if any). Default [false] (only the first will be removed).
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
|
||||||
|
|
@ -507,8 +507,10 @@ val sorted_merge : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> 'a list -
|
||||||
val sorted_diff : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> 'a list -> 'a list
|
val sorted_diff : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> 'a list -> 'a list
|
||||||
(** [sorted_diff ~cmp l1 l2] returns the elements in [l1] that are not in [l2].
|
(** [sorted_diff ~cmp l1 l2] returns the elements in [l1] that are not in [l2].
|
||||||
Both lists are assumed to be sorted with respect to [cmp] and
|
Both lists are assumed to be sorted with respect to [cmp] and
|
||||||
duplicate elements are treated individually. It is the left inverse of
|
duplicate elements in the input lists are treated individually;
|
||||||
[sorted_merge]; that is, [sorted_diff ~cmp (sorted_merge ~cmp l1 l2) l2]
|
for example, [sorted_diff ~cmp [1;1;1;2;2;3] [1;2;2]] would be [[1;1;3]].
|
||||||
|
It is the left inverse of [sorted_merge]; that is,
|
||||||
|
[sorted_diff ~cmp (sorted_merge ~cmp l1 l2) l2]
|
||||||
is always equal to [l1] for sorted lists [l1] and [l2].
|
is always equal to [l1] for sorted lists [l1] and [l2].
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
|
|
@ -521,6 +523,16 @@ val sorted_merge_uniq : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> 'a l
|
||||||
removes duplicates.
|
removes duplicates.
|
||||||
@since 0.10 *)
|
@since 0.10 *)
|
||||||
|
|
||||||
|
val sorted_diff_uniq : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> 'a list -> 'a list
|
||||||
|
(** [sorted_diff_uniq ~cmp l1 l2] collects the elements in [l1] that are not in [l2]
|
||||||
|
and then remove duplicates.
|
||||||
|
Both lists are assumed to be sorted with respect to [cmp] and
|
||||||
|
duplicate elements in the input lists are treated individually;
|
||||||
|
for example, [sorted_diff_uniq ~cmp [1;1;1;2;2] [1;2;2;2]] would be [[1]].
|
||||||
|
[sorted_diff_uniq ~cmp l1 l2] and [uniq_succ ~eq (sorted_diff ~cmp l1 l2)]
|
||||||
|
always give the same result for sorted [l1] and [l2] and compatible [cmp] and [eq].
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val is_sorted : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> bool
|
val is_sorted : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> bool
|
||||||
(** [is_sorted ~cmp l] returns [true] iff [l] is sorted (according to given order).
|
(** [is_sorted ~cmp l] returns [true] iff [l] is sorted (according to given order).
|
||||||
@param cmp the comparison function.
|
@param cmp the comparison function.
|
||||||
|
|
@ -538,8 +550,10 @@ val sorted_insert : cmp:(('a -> 'a -> int) [@keep_label]) -> ?uniq:bool -> 'a ->
|
||||||
@since 0.17 *)
|
@since 0.17 *)
|
||||||
|
|
||||||
val sorted_remove : cmp:(('a -> 'a -> int) [@keep_label]) -> ?all:bool -> 'a -> 'a list -> 'a list
|
val sorted_remove : cmp:(('a -> 'a -> int) [@keep_label]) -> ?all:bool -> 'a -> 'a list -> 'a list
|
||||||
(** [sorted_insert ~cmp x l] removes [x] from a sorted list [l] such that
|
(** [sorted_remove ~cmp x l] removes [x] from a sorted list [l] such that
|
||||||
the return value is sorted too.
|
the return value is sorted too. By default, it is the left inverse of
|
||||||
|
[sorted_insert]; that is, [sorted_remove ~cmp x (sorted_insert ~cmp x l)]
|
||||||
|
is equal to [l] for any sorted list [l].
|
||||||
@param all if true then all occurrences of [x] will be removed. Otherwise, only the first
|
@param all if true then all occurrences of [x] will be removed. Otherwise, only the first
|
||||||
[x] will be removed (if any). Default [false] (only the first will be removed).
|
[x] will be removed (if any). Default [false] (only the first will be removed).
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue