From 556d10a0d401bd034937bb20743336bed75a4509 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 18 Jul 2014 02:51:23 +0200 Subject: [PATCH] CCKList: group,uniq,sort,sort_uniq,repeat and cycle --- core/CCKList.ml | 36 ++++++++++++++++++++++++++++++++++++ core/CCKList.mli | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/core/CCKList.ml b/core/CCKList.ml index 161ef36f..99a56459 100644 --- a/core/CCKList.ml +++ b/core/CCKList.ml @@ -43,6 +43,15 @@ let empty = nil let singleton x () = `Cons (x, nil) +let rec _forever x () = `Cons (x, _forever x) + +let rec _repeat n x () = + if n<=0 then `Nil else `Cons (x, _repeat (n-1) x) + +let repeat ?n x = match n with + | None -> _forever x + | Some n -> _repeat n x + let is_empty l = match l () with | `Nil -> true | `Cons _ -> false @@ -130,6 +139,8 @@ let rec append l1 l2 () = match l1 () with | `Nil -> l2 () | `Cons (x, l1') -> `Cons (x, append l1' l2) +let rec cycle l () = append l (cycle l) () + let rec flat_map f l () = match l () with | `Nil -> `Nil | `Cons (x, l') -> @@ -167,6 +178,22 @@ let product_with f l1 l2 = let product l1 l2 = product_with (fun x y -> x,y) l1 l2 +let rec group eq l () = match l() with + | `Nil -> `Nil + | `Cons (x, l') -> + `Cons (cons x (take_while (eq x) l'), group eq (drop_while (eq x) l')) + +let rec _uniq eq prev l () = match prev, l() with + | _, `Nil -> `Nil + | None, `Cons (x, l') -> + `Cons (x, _uniq eq (Some x) l') + | Some y, `Cons (x, l') -> + if eq x y + then _uniq eq prev l' () + else `Cons (x, _uniq eq (Some x) l') + +let uniq eq l = _uniq eq None l + let rec filter_map f l () = match l() with | `Nil -> `Nil | `Cons (x, l') -> @@ -274,6 +301,15 @@ let to_gen l = l := l'; Some x +let sort ?(cmp=Pervasives.compare) l = + let l = to_list l in + of_list (List.sort cmp l) + +let sort_uniq ?(cmp=Pervasives.compare) l = + let l = to_list l in + uniq (fun x y -> cmp x y = 0) (of_list (List.sort cmp l)) + + (** {2 Monadic Operations} *) module type MONAD = sig type 'a t diff --git a/core/CCKList.mli b/core/CCKList.mli index bd420ea4..003a5892 100644 --- a/core/CCKList.mli +++ b/core/CCKList.mli @@ -47,6 +47,16 @@ val cons : 'a -> 'a t -> 'a t val singleton : 'a -> 'a t +val repeat : ?n:int -> 'a -> 'a t +(** [repeat ~n x] repeats [x] [n] times then stops. If [n] is omitted, + then [x] is repeated forever. + @since NEXT_RELEASE *) + +val cycle : 'a t -> 'a t +(** Cycle through the iterator infinitely. The iterator shouldn't be empty. + @since NEXT_RELEASE *) + + val is_empty : 'a t -> bool val equal : 'a equal -> 'a t equal @@ -87,6 +97,18 @@ val product : 'a t -> 'b t -> ('a * 'b) t (** Specialization of {!product_with} producing tuples @since NEXT_RELEASE *) +val group : 'a equal -> 'a t -> 'a t t +(** [group eq l] groups together consecutive elements that satisfy [eq]. Lazy. + For instance [group (=) [1;1;1;2;2;3;3;1]] yields + [[1;1;1]; [2;2]; [3;3]; [1]] + @since NEXT_RELEASE *) + +val uniq : 'a equal -> 'a t -> 'a t +(** [uniq eq l] returns [l] but removes consecutive duplicates. Lazy. + In other words, if several values that are equal follow one another, + only the first of them is kept. + @since NEXT_RELEASE *) + val flat_map : ('a -> 'b t) -> 'a t -> 'b t val filter_map : ('a -> 'b option) -> 'a t -> 'b t @@ -115,6 +137,16 @@ val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool val merge : 'a ord -> 'a t -> 'a t -> 'a t (** Merge two sorted iterators into a sorted iterator *) +val sort : ?cmp:'a ord -> 'a t -> 'a t +(** Eager sort. Requires the iterator to be finite. O(n ln(n)) time + and space. + @since NEXT_RELEASE *) + +val sort_uniq : ?cmp:'a ord -> 'a t -> 'a t +(** Eager sort that removes duplicate values. Requires the iterator to be + finite. O(n ln(n)) time and space. + @since NEXT_RELEASE *) + (** {2 Implementations} @since NEXT_RELEASE *)