CCList
Complements to List
val empty : 'a t
empty
is []
.
val is_empty : _ t -> bool
is_empty l
returns true
iff l = []
.
cons' l x
is the same as x :: l
. This is convenient for fold functions such as List.fold_left
or Array.fold_left
.
val fold_while : ('a -> 'b -> 'a * [ `Stop | `Continue ]) -> 'a -> 'b t -> 'a
fold_while f init l
folds until a stop condition via ('a, `Stop)
is indicated by the accumulator.
fold_map f init l
is a fold_left
-like function, but it also maps the list to another list.
fold_map_i f init l
is a foldi
-like function, but it also maps the list to another list.
fold_on_map ~f ~reduce init l
combines map f
and fold_left reduce init
in one operation.
scan_left f init l
returns the list [init; f init x0; f (f init x0) x1; …]
where x0
, x1
, etc. are the elements of l
.
reduce f (hd::tl)
returns Some (fold_left f hd tl)
. If l
is empty, then None
is returned.
reduce_exn
is the unsafe version of reduce
.
fold_map2 f init l1 l2
is to fold_map
what List.map2
is to List.map
.
fold_filter_map f init l
is a fold_left
-like function, but also generates a list of output in a way similar to filter_map
.
val fold_filter_map_i :
('acc -> int -> 'a -> 'acc * 'b option) ->
'acc ->
'a list ->
'acc * 'b list
fold_filter_map_i f init l
is a foldi
-like function, but also generates a list of output in a way similar to filter_map
.
fold_flat_map f init l
is a fold_left
-like function, but it also maps the list to a list of lists that is then flatten
'd.
fold_flat_map_i f init l
is a fold_left
-like function, but it also maps the list to a list of lists that is then flatten
'd.
unfold f init
builds up a list from a seed value. When f
produces Some (next_seed, value)
, value
is added to the output list and next_seed
is used in the next call to f
. However, when f
produces None
, list production ends. NOTE if f
never produces None
, then a stack overflow will occur. Therefore, great care must be taken to ensure that f
will produce None
.
count p l
counts how many elements of l
satisfy predicate p
.
count_true_false p l
returns a pair (int1,int2)
where int1
is the number of elements in l
that satisfy the predicate p
, and int2
the number of elements that do not satisfy p
.
val init : int -> (int -> 'a) -> 'a t
init len f
is f 0; f 1; …; f (len-1)
.
combine [a1; …; an] [b1; …; bn]
is [(a1,b1); …; (an,bn)]
. Transform two lists into a list of pairs. Like List.combine
but tail-recursive.
val combine_gen : 'a list -> 'b list -> ('a * 'b) gen
combine_shortest [a1; …; am] [b1; …; bn]
is [(a1,b1); …; (am,bm)]
if m <= n. Like combine
but stops at the shortest list rather than raising.
split [(a1,b1); …; (an,bn)]
is ([a1; …; an], [b1; …; bn])
. Transform a list of pairs into a pair of lists. A tail-recursive version of List.split
.
compare cmp l1 l2
compares the two lists l1
and l2
using the given comparison function cmp
.
compare_lengths l1 l2
compare the lengths of the two lists l1
and l2
. Equivalent to compare (length l1) (length l2)
but more efficient.
val compare_length_with : 'a t -> int -> int
compare_length_with l x
compares the length of the list l
to an integer x
. Equivalent to compare (length l) x
but more efficient.
equal p l1 l2
returns true
if l1
and l2
are equal.
flat_map f l
maps and flattens at the same time (safe). Evaluation order is not guaranteed.
flat_map_i f l
maps with index and flattens at the same time (safe). Evaluation order is not guaranteed.
flatten [l1]; [l2]; …
concatenates a list of lists. Safe version of List.flatten
.
product comb l1 l2
computes the cartesian product of the two lists, with the given combinator comb
.
fold_product f init l1 l2
applies the function f
with the accumulator init
on all the pair of elements of l1
and l2
. Fold on the cartesian product.
cartesian_product [[l1]; [l2]; …; [ln]]
produces the cartesian product of this list of lists, by returning all the ways of picking one element per sublist. NOTE the order of the returned list is unspecified. For example:
# cartesian_product [[1;2];[3];[4;5;6]] |> sort =
[[1;3;4];[1;3;5];[1;3;6];[2;3;4];[2;3;5];[2;3;6]];;
# cartesian_product [[1;2];[];[4;5;6]] = [];;
# cartesian_product [[1;2];[3];[4];[5];[6]] |> sort =
[[1;3;4;5;6];[2;3;4;5;6]];;
invariant: cartesian_product l = map_product id l
.
map_product_l f l
maps each element of l
to a list of objects of type 'b
using f
. We obtain [l1; l2; …; ln]
where length l=n
and li : 'b list
. Then, it returns all the ways of picking exactly one element per li
.
diagonal l
returns all pairs of distinct positions of the list l
, that is the list of List.nth i l, List.nth j l
if i < j
.
val partition_map_either :
('a -> ('b, 'c) CCEither.t) ->
'a list ->
'b list * 'c list
partition_map_either f l
maps f
on l
and gather results in lists:
f x = Left y
, adds y
to the first list.f x = Right z
, adds z
to the second list.val partition_filter_map :
('a -> [< `Left of 'b | `Right of 'c | `Drop ]) ->
'a list ->
'b list * 'c list
partition_filter_map f l
maps f
on l
and gather results in lists:
f x = `Left y
, adds y
to the first list.f x = `Right z
, adds z
to the second list.f x = `Drop
, ignores x
.group_by ?hash ?eq l
groups equal elements, regardless of their order of appearance. precondition: for any x
and y
, if eq x y
then hash x=hash y
must hold.
join ~join_row a b
combines every element of a
with every element of b
using join_row
. If join_row
returns None
, then the two elements do not combine. Assume that b
allows for multiple iterations.
val join_by :
?eq:('key -> 'key -> bool) ->
?hash:('key -> int) ->
('a -> 'key) ->
('b -> 'key) ->
merge:('key -> 'a -> 'b -> 'c option) ->
'a t ->
'b t ->
'c t
join_by ?eq ?hash key1 key2 ~merge la lb
is a binary operation that takes two sequences a
and b
, projects their elements resp. with key1
and key2
, and combine values (x,y)
from (a,b)
with the same key
using merge
. If merge
returns None
, the combination of values is discarded. precondition: for any x
and y
, if eq x y
then hash x=hash y
must hold.
val join_all_by :
?eq:('key -> 'key -> bool) ->
?hash:('key -> int) ->
('a -> 'key) ->
('b -> 'key) ->
merge:('key -> 'a list -> 'b list -> 'c option) ->
'a t ->
'b t ->
'c t
join_all_by ?eq ?hash key1 key2 ~merge la lb
is a binary operation that takes two sequences a
and b
, projects their elements resp. with key1
and key2
, and, for each key k
occurring in at least one of them:
l1
of elements of a
that map to k
l2
of elements of b
that map to k
merge k l1 l2
. If merge
returns None
, the combination of values is discarded, otherwise it returns Some c
and c
is inserted in the result.val group_join_by :
?eq:('a -> 'a -> bool) ->
?hash:('a -> int) ->
('b -> 'a) ->
'a t ->
'b t ->
('a * 'b list) t
group_join_by ?eq ?hash key la lb
associates to every element x
of the first sequence, all the elements y
of the second sequence such that eq x (key y)
. Elements of the first sequences without corresponding values in the second one are mapped to []
precondition: for any x
and y
, if eq x y
then hash x=hash y
must hold.
val sublists_of_len :
?last:('a list -> 'a list option) ->
?offset:int ->
int ->
'a list ->
'a list list
sublists_of_len ?last ?offset n l
returns sub-lists of l
that have length n
. By default, these sub-lists are non overlapping: sublists_of_len 2 [1;2;3;4;5;6]
returns [1;2]; [3;4]; [5;6]
.
Examples:
sublists_of_len 2 [1;2;3;4;5;6] = [[1;2]; [3;4]; [5;6]]
.sublists_of_len 2 ~offset:3 [1;2;3;4;5;6] = [1;2];[4;5]
.sublists_of_len 3 ~last:CCOption.return [1;2;3;4] = [1;2;3];[4]
.sublists_of_len 2 [1;2;3;4;5] = [[1;2]; [3;4]]
.chunks n l
returns consecutives chunks of size at most n
from l
. Each item of l
will occur in exactly one chunk. Only the last chunk might be of length smaller than n
. Invariant: (chunks n l |> List.flatten) = l
.
intersperse x l
inserts the element x
between adjacent elements of the list l
.
interleave [x1…xn] [y1…ym]
is [x1;y1;x2;y2;…]
and finishes with the suffix of the longest list.
val pure : 'a -> 'a t
pure x
is return x
.
val mguard : bool -> unit t
mguard c
is pure ()
if c
is true, []
otherwise. This is useful to define a list by comprehension, e.g.:
# let square_even xs =
let* x = xs in
let* () = mguard (x mod 2 = 0) in
return @@ x * x;;
val square_even : int list -> int list = <fun>
# square_even [1;2;4;3;5;2];;
- : int list = [4; 16; 4]
val return : 'a -> 'a t
return x
is x
.
take_drop n l
returns l1, l2
such that l1 @ l2 = l
and length l1 = min (length l) n
.
take_while f l
returns the longest prefix of l
for which f
is true
.
drop_while f l
drops the longest prefix of l
for which f
is true
.
take_drop_while p l
= take_while p l, drop_while p l
.
last n l
takes the last n
elements of l
(or less if l
doesn't have that many elements).
val head_opt : 'a t -> 'a option
head_opt l
returns Some x
(the first element of the list l
) or None
if the list l
is empty.
tail_opt l
returns Some l'
(the given list l
without its first element) or None
if the list l
is empty.
val last_opt : 'a t -> 'a option
last_opt l
returns Some x
(the last element of l
) or None
if the list l
is empty.
val find_pred : ('a -> bool) -> 'a t -> 'a option
find_pred p l
finds the first element of l
that satisfies p
, or returns None
if no element satisfies p
.
val find_map : ('a -> 'b option) -> 'a t -> 'b option
find_map f l
traverses l
, applying f
to each element. If for some element x
, f x = Some y
, then Some y
is returned. Otherwise the call returns None
.
val find_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b option
find_mapi f l
is like find_map
, but also pass the index to the predicate function.
val find_idx : ('a -> bool) -> 'a t -> (int * 'a) option
find_idx p x
returns Some (i,x)
where x
is the i
-th element of l
, and p x
holds. Otherwise returns None
.
remove ~eq ~key l
removes every instance of key
from l
. Tail-recursive.
filter_map f l
is the sublist of l
containing only elements for which f
returns Some e
. Map and remove elements at the same time.
keep_some l
retains only elements of the form Some x
. Like filter_map CCFun.id
.
all_some l
returns Some l'
if all elements of l
are of the form Some x
, or None
otherwise.
all_ok l
returns Ok l'
if all elements of l
are of the form Ok x
, or Error e
otherwise (with the first error met).
Split a list of results into Ok
s and Error
s.
sorted_mem ~cmp x l
and mem x l
give the same result for any sorted list l
, but potentially more efficiently.
sorted_merge ~cmp l1 l2
merges elements from both sorted list using the given comparison function cmp
.
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 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
.
sort_uniq ~cmp l
sorts the list l
using the given comparison function cmp
and remove duplicate elements.
sorted_merge_uniq ~cmp l1 l2
merges the sorted lists l1
and l2
and removes duplicates.
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
.
is_sorted ~cmp l
returns true
iff l
is sorted (according to given order).
sorted_insert ~cmp ?uniq x l
inserts x
into l
such that, if l
was sorted, then sorted_insert x l
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
.
uniq_succ ~eq l
removes duplicate elements that occur one next to the other. Examples: uniq_succ ~eq:(=) [1;2;1] = [1;2;1]
. uniq_succ ~eq:(=) [1;1;2] = [1;2]
.
group_succ ~eq l
groups together consecutive elements that are equal according to eq
.
mapi f l
is like map
, but the function f
is applied to the index of the element as first argument (counting from 0), and the element itself as second argument.
val iteri : (int -> 'a -> unit) -> 'a t -> unit
iteri f l
is like iter
, but the function f
is applied to the index of the element as first argument (counting from 0), and the element itself as second argument.
iteri2 f l1 l2
applies f
to the two lists l1
and l2
simultaneously. The integer passed to f
indicates the index of element.
val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
foldi f init l
is like fold
but it also passes in the index of each element, from 0
to length l - 1
as additional argument to the folded function f
. Tail-recursive.
foldi2 f init l1 l2
folds on the two lists l1
and l2
, with index of each element passed to the function f
. Computes f(… (f init i_0 l1_0 l2_0) …) i_n l1_n l2_n
.
val get_at_idx : int -> 'a t -> 'a option
get_at_idx i l
returns Some i-th
element of the given list l
or None
if the list l
is too short. If the index is negative, it will get element starting from the end of the list l
.
val nth_opt : 'a t -> int -> 'a option
nth_opt l n
returns Some n-th
element of l
. Safe version of nth
.
val get_at_idx_exn : int -> 'a t -> 'a
get_at_idx_exn i l
gets the i-th
element of l
, or
set_at_idx i x l
replaces the i-th
element with x
(removes the old one), or does nothing if index is too high. If the index is negative, it will set element starting from the end of the list.
insert_at_idx i x l
inserts x
at i-th
position, between the two existing elements. If the index is too high, append at the end of the list. If the index is negative, it will insert element starting from the end of the list.
remove_at_idx i l
removes element at given index i
. Does nothing if the index is too high. If the index is negative, it will remove element starting from the end of the list.
Those operations maintain the invariant that the list does not contain duplicates (if it already satisfies it).
add_nodup ~eq x set
adds x
to set
if it was not already present. Linear time.
remove_one ~eq x set
removes one occurrence of x
from set
. Linear time.
val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool
mem ?eq x l
is true
iff x
is equal to an element of l
. A comparator function eq
can be provided. Linear time.
subset ~eq l1 l2
tests if all elements of the list l1
are contained in the list l2
by applying eq
.
uniq ~eq l
removes duplicates in l
w.r.t the equality predicate eq
. Complexity is quadratic in the length of the list, but the order of elements is preserved. If you wish for a faster de-duplication but do not care about the order, use sort_uniq
.
union ~eq l1 l2
is the union of the lists l1
and l2
w.r.t. the equality predicate eq
. Complexity is product of length of inputs.
inter ~eq l1 l2
is the intersection of the lists l1
and l2
w.r.t. the equality predicate eq
. Complexity is product of length of inputs.
val range_by : step:int -> int -> int -> int t
range_by ~step i j
iterates on integers from i
to j
included, where the difference between successive elements is step
. Use a negative step
for a decreasing list.
val range : int -> int -> int t
range i j
iterates on integers from i
to j
included. It works both for decreasing and increasing ranges.
val range' : int -> int -> int t
range' i j
is like range
but the second bound j
is excluded. For instance range' 0 5 = [0;1;2;3;4]
.
val replicate : int -> 'a -> 'a t
replicate n x
replicates the given element x
n
times.
module Assoc : sig ... end
val assoc : eq:('a -> 'a -> bool) -> 'a -> ('a * 'b) t -> 'b
assoc ~eq k alist
returns the value v
associated with key k
in alist
. Like Assoc.get_exn
.
val assoc_opt : eq:('a -> 'a -> bool) -> 'a -> ('a * 'b) t -> 'b option
assoc_opt ~eq k alist
returns Some v
if the given key k
is present into alist
, or None
if not present. Like Assoc.get
.
val assq_opt : 'a -> ('a * 'b) t -> 'b option
assq_opt k alist
returns Some v
if the given key k
is present into alist
. Like Assoc.assoc_opt
but use physical equality instead of structural equality to compare keys. Safe version of assq
.
val mem_assoc : ?eq:('a -> 'a -> bool) -> 'a -> ('a * _) t -> bool
mem_assoc ?eq k alist
returns true
iff k
is a key in alist
. Like Assoc.mem
.
remove_assoc ~eq k alist
returns the alist
without the first pair with key k
, if any. Like Assoc.remove
.
module Ref : sig ... end
module type MONAD = sig ... end
val random : 'a random_gen -> 'a t random_gen
val random_non_empty : 'a random_gen -> 'a t random_gen
val random_len : int -> 'a random_gen -> 'a t random_gen
val random_choose : 'a t -> 'a random_gen
random_choose l
randomly chooses an element in the list l
.
val random_sequence : 'a random_gen t -> 'a t random_gen
val to_string :
?start:string ->
?stop:string ->
?sep:string ->
('a -> string) ->
'a t ->
string
to_string ?start ?stop ?sep item_to_string l
prints l
to a string using sep
as a separator between elements of l
.
val to_seq : 'a t -> 'a Stdlib.Seq.t
to_seq l
returns a Seq.t
of the elements of the list l
. Renamed from to_std_seq
since 3.0.
of_iter iter
builds a list from a given iter
. In the result, elements appear in the same order as they did in the source iter
.
val of_seq_rev : 'a Stdlib.Seq.t -> 'a t
of_seq_rev seq
builds a list from a given Seq.t
, in reverse order. Renamed from to_std_seq_rev
since 3.0.
val of_seq : 'a Stdlib.Seq.t -> 'a t
of_seq seq
builds a list from a given Seq.t
. In the result, elements appear in the same order as they did in the source Seq.t
. Renamed from of_std_seq
since 3.0.
of_gen gen
builds a list from a given gen
. In the result, elements appear in the same order as they did in the source gen
.
It is convenient to open
CCList.Infix
to access the infix operators without cluttering the scope too much.
module Infix : sig ... end
include module type of Infix
val (--) : int -> int -> int t
i -- j
is the infix alias for range
. Bounds included.
val (--^) : int -> int -> int t
i --^ j
is the infix alias for range'
. Second bound j
excluded.
(and&)
is combine_shortest
. It allows to perform a synchronized product between two lists, stopping gently at the shortest. Usable both with let+
and let*
.
# let f xs ys zs =
let+ x = xs
and& y = ys
and& z = zs in
x + y + z;;
val f : int list -> int list -> int list -> int list = <fun>
# f [1;2] [5;6;7] [10;10];;
- : int list = [16; 18]