From 8c06c13563ba27b64c9cf79db9d6875bef253a2e Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sat, 22 Aug 2015 23:49:36 +0200 Subject: [PATCH] add `group_by` (ignores the ordering) --- sequence.ml | 16 ++++++++++++++++ sequence.mli | 5 +++++ tests/test_sequence.ml | 12 +++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/sequence.ml b/sequence.ml index 1401c8d..c781d53 100644 --- a/sequence.ml +++ b/sequence.ml @@ -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 *) diff --git a/sequence.mli b/sequence.mli index 4104b02..56969c5 100644 --- a/sequence.mli +++ b/sequence.mli @@ -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 diff --git a/tests/test_sequence.ml b/tests/test_sequence.ml index 8fd1b17..a85a5c6 100644 --- a/tests/test_sequence.ml +++ b/tests/test_sequence.ml @@ -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;