package jhupllib

  1. Overview
  2. Docs

Source file multimap.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
open Batteries;;

module type Multimap_sig =
sig
  type t
  type key
  type value

  module M : Map.S with type key = key
  module S : Set.S with type elt = value

  val empty : t

  val is_empty : t -> bool

  val num_keys : t -> int

  val num_values : t -> int

  val add : key -> value -> t -> t

  val add_all : key -> value Enum.t -> t -> t

  val find : key -> t -> value Enum.t

  val remove : key -> value -> t -> t

  val remove_all : key -> t -> t

  val mem : key -> value -> t -> bool

  val mem_any : key -> t -> bool

  val singleton : key -> value -> t

  val keys : t -> key Enum.t

  val enum : t -> (key * value) Enum.t

  val of_enum : (key * value) Enum.t -> t

  val enum_by_key : t -> (key * S.t) Enum.t

  val equal : t -> t -> bool

  val compare : t -> t -> int
end;;

module Make(Key_ord : BatInterfaces.OrderedType)
    (Value_ord : BatInterfaces.OrderedType)
  : Multimap_sig with type key = Key_ord.t and type value = Value_ord.t =
struct
  module M = Map.Make(Key_ord);;
  module S = Set.Make(Value_ord);;

  type t = S.t M.t;;
  type key = Key_ord.t;;
  type value = Value_ord.t;;

  let empty = M.empty;;

  let is_empty m = M.is_empty m;;

  let num_keys m = M.cardinal m;;

  let num_values m =
    M.enum m
    |> Enum.fold (fun a (_,v) -> a + S.cardinal v) 0
  ;;

  let find_internal k m =
    match M.Exceptionless.find k m with
    | None -> S.empty
    | Some v -> v
  ;;

  let add k v m =
    let old_set = find_internal k m in
    let new_set = S.add v old_set in
    M.add k new_set m
  ;;

  let add_all k vs m =
    let old_set = find_internal k m in
    let new_set = Enum.fold (flip S.add) old_set vs in
    M.add k new_set m
  ;;

  let find k m =
    match M.Exceptionless.find k m with
    | None -> Enum.empty ()
    | Some v -> S.enum v
  ;;

  let remove k v m =
    let old_set = find_internal k m in
    let new_set = S.remove v old_set in
    if S.is_empty new_set
    then M.remove k m
    else M.add k new_set m
  ;;

  let remove_all k m =
    M.remove k m
  ;;

  let mem k v m =
    find_internal k m |> S.mem v
  ;;

  let mem_any k m =
    M.mem k m
  ;;

  let singleton k v = M.add k (S.singleton v) M.empty;;

  let keys m = M.keys m;;

  let enum m =
    M.enum m
    |> Enum.map
      (fun (k,vs) ->
         S.enum vs |> Enum.map (fun v -> (k,v))
      )
    |> Enum.concat
  ;;

  let of_enum =
    Enum.fold (fun a (k,v) -> add k v a) empty
  ;;

  let enum_by_key m =
    M.enum m
  ;;

  let compare x y = M.compare S.compare x y;;

  let equal x y = compare x y == 0;;
end;;
OCaml

Innovation. Community. Security.