feat(list): add {interleave,intersperse} (closes #191)

This commit is contained in:
Simon Cruanes 2018-03-28 20:10:14 -05:00
parent 89fc7f9c77
commit 5986955fb6
2 changed files with 59 additions and 2 deletions

View file

@ -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
| [] -> []

View file

@ -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]. *)