add CCList.{take,drop}_while; improve map performance

This commit is contained in:
Simon Cruanes 2015-09-19 17:35:59 +02:00
parent 96c62d9048
commit 8b228ec8cb
2 changed files with 58 additions and 6 deletions

View file

@ -40,12 +40,16 @@ let direct_depth_default_ = 1000
let map f l = let map f l =
let rec direct f i l = match l with let rec direct f i l = match l with
| [] -> [] | [] -> []
| _ when i=0 -> safe f l | [x] -> [f x]
| x::l' -> | [x1;x2] -> let y1 = f x1 in [y1; f x2]
let y = f x in | [x1;x2;x3] -> let y1 = f x1 in let y2 = f x2 in [y1; y2; f x3]
y :: direct f (i-1) l' | _ when i=0 -> List.rev (List.rev_map f l)
and safe f l = | x1::x2::x3::x4::l' ->
List.rev (List.rev_map f l) let y1 = f x1 in
let y2 = f x2 in
let y3 = f x3 in
let y4 = f x4 in
y1 :: y2 :: y3 :: y4 :: direct f (i-1) l'
in in
direct f direct_depth_default_ l direct f direct_depth_default_ l
@ -395,6 +399,13 @@ let take n l =
take 300_000 (1 -- 400_000) = 1 -- 300_000 take 300_000 (1 -- 400_000) = 1 -- 300_000
*) *)
(*$Q
(Q.pair (Q.list Q.small_int) Q.int) (fun (l,i) -> \
let i = abs i in \
let l1 = take i l in \
List.length l1 <= i && ((List.length l1 = i) = (List.length l >= i)))
*)
let rec drop n l = match l with let rec drop n l = match l with
| [] -> [] | [] -> []
| _ when n=0 -> l | _ when n=0 -> l
@ -411,6 +422,41 @@ let split = take_drop
l1 @ l2 = l ) l1 @ l2 = l )
*) *)
let take_while p l =
let rec direct i p l = match l with
| [] -> []
| _ when i=0 -> safe p [] l
| x :: l' ->
if p x then x :: direct (i-1) p l' else []
and safe p acc l = match l with
| [] -> List.rev acc
| x :: l' ->
if p x then safe p (x::acc) l' else List.rev acc
in
direct direct_depth_default_ p l
(*$T
take_while (fun x->x<10) (1 -- 20) = (1--9)
take_while (fun x->x <> 0) [0;1;2;3] = []
take_while (fun _ -> true) [] = []
take_while (fun _ -> true) (1--10) = (1--10)
*)
(*$Q
Q.(pair (fun1 small_int bool) (list small_int)) (fun (f,l) -> \
let l1 = take_while f l in \
List.for_all f l1)
*)
let rec drop_while p l = match l with
| [] -> []
| x :: l' -> if p x then drop_while p l' else l
(*$Q
Q.(pair (fun1 small_int bool) (list small_int)) (fun (f,l) -> \
take_while f l @ drop_while f l = l)
*)
let last n l = let last n l =
let len = List.length l in let len = List.length l in
if len < n then l else drop (len-n) l if len < n then l else drop (len-n) l

View file

@ -118,6 +118,12 @@ val take_drop : int -> 'a t -> 'a t * 'a t
(** [take_drop n l] returns [l1, l2] such that [l1 @ l2 = l] and (** [take_drop n l] returns [l1, l2] such that [l1 @ l2 = l] and
[length l1 = min (length l) n] *) [length l1 = min (length l) n] *)
val take_while : ('a -> bool) -> 'a t -> 'a t
(** @since NEXT_RELEASE *)
val drop_while : ('a -> bool) -> 'a t -> 'a t
(** @since NEXT_RELEASE *)
val split : int -> 'a t -> 'a t * 'a t val split : int -> 'a t -> 'a t * 'a t
(** synonym to {!take_drop} (** synonym to {!take_drop}
@deprecated since NEXT_RELEASE: conflict with the {!List.split} standard function *) @deprecated since NEXT_RELEASE: conflict with the {!List.split} standard function *)