mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
added PHashtbl.get_eq/get_hash, to access the functions;
added a function to create a PHashtbl from a module; added PHashtbl.map
This commit is contained in:
parent
01e008256c
commit
25a7d33985
3 changed files with 62 additions and 2 deletions
26
pHashtbl.ml
26
pHashtbl.ml
|
|
@ -51,6 +51,17 @@ let create ?(max_load=0.8) ?(eq=fun x y -> x = y)
|
||||||
eq;
|
eq;
|
||||||
hash; }
|
hash; }
|
||||||
|
|
||||||
|
module type Hashable = sig
|
||||||
|
type t
|
||||||
|
val equal : t -> t -> bool
|
||||||
|
val hash : t -> int
|
||||||
|
end
|
||||||
|
|
||||||
|
(** Create a hashtable from the given 'typeclass' *)
|
||||||
|
let create_tc (type key) (h : (module Hashable with type t = key)) size =
|
||||||
|
let module H = (val h) in
|
||||||
|
create ~eq:H.equal ~hash:H.hash size
|
||||||
|
|
||||||
(** Copy of the hashtable *)
|
(** Copy of the hashtable *)
|
||||||
let copy t = {
|
let copy t = {
|
||||||
eq = t.eq;
|
eq = t.eq;
|
||||||
|
|
@ -179,6 +190,17 @@ let fold f acc t =
|
||||||
done;
|
done;
|
||||||
!acc
|
!acc
|
||||||
|
|
||||||
|
(** Map, replaces values by other values *)
|
||||||
|
let map f t =
|
||||||
|
let t' = create ~eq:t.eq ~hash:t.hash (Array.length t.buckets) in
|
||||||
|
for i = 0 to Array.length t.buckets - 1 do
|
||||||
|
match t.buckets.(i) with
|
||||||
|
| (_, _, Empty) -> ()
|
||||||
|
| (k, _, Deleted) -> t'.buckets.(i) <- my_deleted k
|
||||||
|
| (k, v, Used) -> t'.buckets.(i) <- (k, f k v, Used)
|
||||||
|
done;
|
||||||
|
t'
|
||||||
|
|
||||||
(** Destructive filter (remove bindings that do not satisfiy predicate) *)
|
(** Destructive filter (remove bindings that do not satisfiy predicate) *)
|
||||||
let filter pred t =
|
let filter pred t =
|
||||||
for i = 0 to Array.length t.buckets - 1 do
|
for i = 0 to Array.length t.buckets - 1 do
|
||||||
|
|
@ -201,3 +223,7 @@ let to_seq t =
|
||||||
|
|
||||||
(** Statistics on the table *)
|
(** Statistics on the table *)
|
||||||
let stats t = (Array.length t.buckets, t.size, t.size, 0, 0, 1)
|
let stats t = (Array.length t.buckets, t.size, t.size, 0, 0, 1)
|
||||||
|
|
||||||
|
let get_eq t = t.eq
|
||||||
|
|
||||||
|
let get_hash t = t.hash
|
||||||
|
|
|
||||||
28
pHashtbl.mli
28
pHashtbl.mli
|
|
@ -25,8 +25,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
(** {1 Open addressing hashtable, with linear probing} *)
|
(** {1 Open addressing hashtable, with linear probing} *)
|
||||||
|
|
||||||
type ('a, 'b) t
|
type ('a, 'b) t = private {
|
||||||
(** Polymorphic hashtable *)
|
mutable buckets : ('a * 'b * state) array;
|
||||||
|
mutable size : int;
|
||||||
|
eq : 'a -> 'a -> bool;
|
||||||
|
hash : 'a -> int;
|
||||||
|
max_load : float;
|
||||||
|
} (** A hashtable is an array of (key, value) buckets that have a state,
|
||||||
|
plus the size of the table and equality/hash functions *)
|
||||||
|
and state = Used | Empty | Deleted
|
||||||
|
(** state of a bucket *)
|
||||||
|
|
||||||
val create : ?max_load:float -> ?eq:('a -> 'a -> bool) ->
|
val create : ?max_load:float -> ?eq:('a -> 'a -> bool) ->
|
||||||
?hash:('a -> int) -> int -> ('a, 'b) t
|
?hash:('a -> int) -> int -> ('a, 'b) t
|
||||||
|
|
@ -34,6 +42,15 @@ val create : ?max_load:float -> ?eq:('a -> 'a -> bool) ->
|
||||||
and must be in ]0, 1[. Functions for equality check and hashing
|
and must be in ]0, 1[. Functions for equality check and hashing
|
||||||
can also be provided. *)
|
can also be provided. *)
|
||||||
|
|
||||||
|
module type Hashable = sig
|
||||||
|
type t
|
||||||
|
val equal : t -> t -> bool
|
||||||
|
val hash : t -> int
|
||||||
|
end
|
||||||
|
|
||||||
|
val create_tc : (module Hashable with type t = 'a) -> int -> ('a, 'b) t
|
||||||
|
(** Create a hashtable from the given 'typeclass' *)
|
||||||
|
|
||||||
val copy : ('a, 'b) t -> ('a, 'b) t
|
val copy : ('a, 'b) t -> ('a, 'b) t
|
||||||
(** Copy of the hashtable *)
|
(** Copy of the hashtable *)
|
||||||
|
|
||||||
|
|
@ -61,6 +78,9 @@ val mem : ('a,_) t -> 'a -> bool
|
||||||
val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit
|
val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit
|
||||||
(** Iterate on bindings *)
|
(** Iterate on bindings *)
|
||||||
|
|
||||||
|
val map : ('a -> 'b -> 'c) -> ('a, 'b) t -> ('a, 'c) t
|
||||||
|
(** Map, replaces values by other values *)
|
||||||
|
|
||||||
val filter : ('a -> 'b -> bool) -> ('a, 'b) t -> unit
|
val filter : ('a -> 'b -> bool) -> ('a, 'b) t -> unit
|
||||||
(** Destructive filter (remove bindings that do not satisfiy predicate) *)
|
(** Destructive filter (remove bindings that do not satisfiy predicate) *)
|
||||||
|
|
||||||
|
|
@ -75,3 +95,7 @@ val to_seq : ('a, 'b) t -> ('a * 'b) Sequence.t
|
||||||
|
|
||||||
val stats : (_, _) t -> int * int * int * int * int * int
|
val stats : (_, _) t -> int * int * int * int * int * int
|
||||||
(** Cf Weak.S *)
|
(** Cf Weak.S *)
|
||||||
|
|
||||||
|
val get_eq : ('v, _) t -> ('v -> 'v -> bool)
|
||||||
|
|
||||||
|
val get_hash : ('v, _) t -> ('v -> int)
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,16 @@ let test_filter () =
|
||||||
OUnit.assert_bool "mem" (PHashtbl.mem h 4);
|
OUnit.assert_bool "mem" (PHashtbl.mem h 4);
|
||||||
OUnit.assert_bool "mem" (PHashtbl.mem h 2)
|
OUnit.assert_bool "mem" (PHashtbl.mem h 2)
|
||||||
|
|
||||||
|
let test_map () =
|
||||||
|
let h = PHashtbl.create 5 in
|
||||||
|
PHashtbl.of_seq h my_seq;
|
||||||
|
let h' = PHashtbl.map (fun k v -> String.uppercase v) h in
|
||||||
|
OUnit.assert_equal (PHashtbl.length h') 4;
|
||||||
|
OUnit.assert_equal (PHashtbl.find h' 1) "A";
|
||||||
|
OUnit.assert_equal (PHashtbl.find h' 2) "B";
|
||||||
|
OUnit.assert_equal (PHashtbl.find h' 3) "C";
|
||||||
|
OUnit.assert_equal (PHashtbl.find h' 4) "D"
|
||||||
|
|
||||||
let suite =
|
let suite =
|
||||||
"test_pHashtbl" >:::
|
"test_pHashtbl" >:::
|
||||||
[ "test_add" >:: test_add;
|
[ "test_add" >:: test_add;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue