add group_by (ignores the ordering)

This commit is contained in:
Simon Cruanes 2015-08-22 23:49:36 +02:00
parent d6b7131fd8
commit 8c06c13563
3 changed files with 30 additions and 3 deletions

View file

@ -253,6 +253,22 @@ let group_succ_by ?(eq=fun x y -> x = y) seq k =
let group = group_succ_by
let group_by (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq =
let module Tbl = Hashtbl.Make(struct
type t = k
let equal = eq
let hash = hash
end) in
(* compute group table *)
let tbl = Tbl.create 32 in
seq
(fun x ->
let l = try Tbl.find tbl x with Not_found -> [] in
Tbl.replace tbl x (x::l)
);
fun yield ->
Tbl.iter (fun _ l -> yield l) tbl
let uniq ?(eq=fun x y -> x = y) seq k =
let has_prev = ref false
and prev = ref (Obj.magic 0) in (* avoid option type, costly *)

View file

@ -223,6 +223,11 @@ val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
Synonym to {!group}.
@since NEXT_RELEASE *)
val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) ->
'a t -> 'a list t
(** Group equal elements, disregarding their order of appearance.
The result sequence is traversable as many times as required.
@since NEXT_RELEASE *)
val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
(** Remove consecutive duplicate elements. Basically this is

View file

@ -124,11 +124,16 @@ let test_sort_uniq () =
|> S.to_list
|> OUnit.assert_equal [1;2;3;4;5;42]
let test_group () =
let test_group_succ () =
[1;2;3;3;2;2;3;4]
|> S.of_list |> S.group ?eq:None |> S.to_list
|> S.of_list |> S.group_succ_by ?eq:None |> S.to_list
|> OUnit.assert_equal [[1];[2];[3;3];[2;2];[3];[4]]
let test_group_by () =
[1;2;3;3;2;2;3;4]
|> S.of_list |> S.group_by ?eq:None ?hash:None |> S.sort ?cmp:None |> S.to_list
|> OUnit.assert_equal [[1];[2;2;2];[3;3;3];[4]]
let test_uniq () =
[1;2;2;3;4;4;4;3;3]
|> S.of_list |> S.uniq ?eq:None |> S.to_list
@ -226,7 +231,8 @@ let suite =
"test_big_persistent" >:: test_big_persistent;
"test_sort" >:: test_sort;
"test_sort_uniq" >:: test_sort;
"test_group" >:: test_group;
"test_group_succ_by" >:: test_group_succ;
"test_group_by" >:: test_group_by;
"test_uniq" >:: test_uniq;
"test_product" >:: test_product;
"test_join" >:: test_join;