add {union,inter,diff,subset}

This commit is contained in:
Simon Cruanes 2017-02-02 22:04:29 +01:00
parent 6c7d59042a
commit 40f33f6f96
2 changed files with 90 additions and 0 deletions

View file

@ -613,6 +613,52 @@ let group_join_by (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) f c1 c2 =
|> sort |> to_list)
*)
let union (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) c1 c2 =
let module Tbl = Hashtbl.Make(struct
type t = a let equal = eq let hash = hash end) in
let tbl = Tbl.create 32 in
c1 (fun x -> Tbl.replace tbl x ());
c2 (fun x -> Tbl.replace tbl x ());
fun yield -> Tbl.iter (fun x _ -> yield x) tbl
type inter_status =
| Inter_left
| Inter_both
let inter (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) c1 c2 =
let module Tbl = Hashtbl.Make(struct
type t = a let equal = eq let hash = hash end) in
let tbl = Tbl.create 32 in
c1 (fun x -> Tbl.replace tbl x Inter_left);
c2
(fun x ->
try
match Tbl.find tbl x with
| Inter_left ->
Tbl.replace tbl x Inter_both; (* save *)
| Inter_both -> ()
with Not_found -> ());
fun yield -> Tbl.iter (fun x res -> if res=Inter_both then yield x) tbl
let diff (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) c1 c2 =
let module Tbl = Hashtbl.Make(struct
type t = a let equal = eq let hash = hash end) in
let tbl = Tbl.create 32 in
c2 (fun x -> Tbl.replace tbl x ());
fun yield ->
c1 (fun x -> if not (Tbl.mem tbl x) then yield x)
exception Subset_exit
let subset (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) c1 c2 =
let module Tbl = Hashtbl.Make(struct
type t = a let equal = eq let hash = hash end) in
let tbl = Tbl.create 32 in
c2 (fun x -> Tbl.replace tbl x ());
try
c1 (fun x -> if not (Tbl.mem tbl x) then raise Subset_exit);
true
with Subset_exit -> false
let rec unfoldr f b k = match f b with
| None -> ()

View file

@ -331,6 +331,50 @@ val group_join_by : ?eq:'a equal -> ?hash:'a hash ->
are mapped to [[]]
@since NEXT_RELEASE *)
val inter :
?eq:'a equal -> ?hash:'a hash ->
'a t -> 'a t -> 'a t
(** Intersection of two collections. Each element will occur at most once
in the result. Eager.
@since NEXT_RELEASE *)
(*$=
[2;4;5;6] (inter (1--6) (cons 2 (4--10)) |> sort |> to_list)
[] (inter (0--5) (6--10) |> to_list)
*)
val union :
?eq:'a equal -> ?hash:'a hash ->
'a t -> 'a t -> 'a t
(** Union of two collections. Each element will occur at most once
in the result. Eager.
@since NEXT_RELEASE *)
(*$=
[2;4;5;6] (union (4--6) (cons 2 (4--5)) |> sort |> to_list)
*)
val diff :
?eq:'a equal -> ?hash:'a hash ->
'a t -> 'a t -> 'a t
(** Set difference. Eager.
@since NEXT_RELEASE *)
(*$=
[1;2;8;9;10] (diff (1--10) (3--7) |> to_list)
*)
val subset :
?eq:'a equal -> ?hash:'a hash ->
'a t -> 'a t -> bool
(** [subset a b] returns [true] if all elements of [a] belong to [b]. Eager.
@since NEXT_RELEASE *)
(*$T
subset (2 -- 4) (1 -- 4)
not (subset (1 -- 4) (2 -- 10))
*)
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
(** [unfoldr f b] will apply [f] to [b]. If it
yields [Some (x,b')] then [x] is returned