feat(list): add sorted_diff_uniq

Also fixed documentation
This commit is contained in:
favonia 2021-05-24 09:23:11 -05:00
parent 80e403c969
commit 8d532f9a00
3 changed files with 70 additions and 8 deletions

View file

@ -958,6 +958,40 @@ let sorted_merge_uniq ~cmp l1 l2 =
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 rec direct i n l = match l with
| [] -> []

View file

@ -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
(** [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
duplicate elements are treated individually. It is the left inverse of
[sorted_merge]; that is, [sorted_diff ~cmp (sorted_merge ~cmp l1 l2) l2]
duplicate elements in the input lists are treated individually;
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].
@since NEXT_RELEASE *)
@ -518,6 +520,16 @@ val sorted_merge_uniq : cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
removes duplicates.
@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
(** [is_sorted ~cmp l] returns [true] iff [l] is sorted (according to given order).
@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 *)
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
the return value is sorted too.
(** [sorted_remove ~cmp x l] removes [x] from a sorted list [l] such that
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
[x] will be removed (if any). Default [false] (only the first will be removed).
@since NEXT_RELEASE *)

View file

@ -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
(** [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
duplicate elements are treated individually. It is the left inverse of
[sorted_merge]; that is, [sorted_diff ~cmp (sorted_merge ~cmp l1 l2) l2]
duplicate elements in the input lists are treated individually;
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].
@since NEXT_RELEASE *)
@ -521,6 +523,16 @@ val sorted_merge_uniq : cmp:(('a -> 'a -> int) [@keep_label]) -> 'a list -> 'a l
removes duplicates.
@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
(** [is_sorted ~cmp l] returns [true] iff [l] is sorted (according to given order).
@param cmp the comparison function.
@ -538,8 +550,10 @@ val sorted_insert : cmp:(('a -> 'a -> int) [@keep_label]) -> ?uniq:bool -> 'a ->
@since 0.17 *)
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
the return value is sorted too.
(** [sorted_remove ~cmp x l] removes [x] from a sorted list [l] such that
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
[x] will be removed (if any). Default [false] (only the first will be removed).
@since NEXT_RELEASE *)