From 5986955fb6ace1261619b0ad2a5201fe5d4cf420 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 28 Mar 2018 20:10:14 -0500 Subject: [PATCH] feat(list): add `{interleave,intersperse}` (closes #191) --- src/core/CCList.ml | 50 ++++++++++++++++++++++++++++++++++++++++++++- src/core/CCList.mli | 11 +++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/core/CCList.ml b/src/core/CCList.ml index 8a4dbfb0..30ef12a1 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -580,7 +580,7 @@ let sorted_merge ~cmp l1 l2 = List.length (sorted_merge ~cmp:CCInt.compare l1 l2) = List.length l1 + List.length l2) *) -let sort_uniq (type elt) ~cmp l = List.sort_uniq cmp l +let sort_uniq ~cmp l = List.sort_uniq cmp l (*$T sort_uniq ~cmp:CCInt.compare [1;2;5;3;6;1;4;2;3] = [1;2;3;4;5;6] @@ -786,6 +786,54 @@ let sublists_of_len ?(last=fun _ -> None) ?offset n l = [[1;2]; [3;4]] (subs 2 [1;2;3;4;5]) *) +let intersperse x l = + let rec aux_direct i x l = match l with + | [] -> [] + | [_] -> l + | _ when i=0 -> aux_tailrec [] x l + | y :: tail -> y :: x :: aux_direct (i-1) x tail + and aux_tailrec acc x l = match l with + | [] -> List.rev acc + | [y] -> List.rev (y::acc) + | y :: tail -> aux_tailrec (x :: y :: acc) x tail + in + aux_direct 1_000 x l + +(*$= + [] (intersperse 0 []) + [1] (intersperse 0 [1]) + [1;0;2;0;3;0;4] (intersperse 0 [1;2;3;4]) +*) + +(*$Q + Q.(pair int (list int)) (fun (x,l) -> \ + length (intersperse x l) = (if length l <= 1 then length l else 2 * length l-1)) + Q.(pair int (list int)) (fun (x,l) -> \ + rev (intersperse x l) = intersperse x (rev l)) +*) + +let interleave l1 l2 : _ list = + let rec aux acc l1 l2 = match l1, l2 with + | [], [] -> List.rev acc + | [], _ -> List.rev (List.rev_append l2 acc) + | _, [] -> List.rev (List.rev_append l1 acc) + | x1 :: tl1, x2 :: tl2 -> + aux (x2 :: x1 :: acc) tl1 tl2 + in + aux [] l1 l2 + +(*$= + [1;2;3;4;5] (interleave [1;3] [2;4;5]) + [1;2;3] (interleave [1] [2;3]) +*) + +(*$Q + Q.(pair (small_list int)(small_list int)) (fun (l1,l2) -> \ + length (interleave l1 l2) = length l1 + length l2) + Q.(small_list int) (fun l -> l = interleave [] l) + Q.(small_list int) (fun l -> l = interleave l []) +*) + let take_while p l = let rec direct i p l = match l with | [] -> [] diff --git a/src/core/CCList.mli b/src/core/CCList.mli index a9ed88d2..2b8261c5 100644 --- a/src/core/CCList.mli +++ b/src/core/CCList.mli @@ -45,7 +45,7 @@ val (@) : 'a t -> 'a t -> 'a t Concatenate two lists. *) val filter : ('a -> bool) -> 'a t -> 'a t -(** Safe version of {!List.filter}. +(** Safe version of {!List.filter}. [filter p l] returns all the elements of the list [l] that satisfy the predicate [p]. The order of the elements in the input list is preserved. *) @@ -202,6 +202,15 @@ val sublists_of_len : @raise Invalid_argument if [offset <= 0] or [n <= 0]. @since 1.0 *) +val intersperse : 'a -> 'a list -> 'a list +(** Insert the first argument between every element of the list + @since NEXT_RELEASE *) + +val interleave : 'a list -> 'a list -> 'a list +(** [interleave [x1…xn] [y1…ym]] is [x1,y1,x2,y2,…] and finishes with + the suffix of the longest list + @since NEXT_RELEASE *) + val pure : 'a -> 'a t (** [pure] is [return]. *)