|
4 | 4 | reader-error]]) |
5 | 5 | (:require-macros [cljs.core :as coreclj])) |
6 | 6 |
|
7 | | -(deftype PersistentPriorityMap [priority->set-of-items item->priority meta ^:mutable __hash] |
| 7 | +(deftype PersistentPriorityMap [priority->set-of-items item->priority meta keyfn ^:mutable __hash] |
8 | 8 | IPrintWithWriter |
9 | 9 | (-pr-writer [coll writer opts] |
10 | 10 | (let [pr-pair (fn [keyval] (pr-sequential-writer writer pr-writer "" " " "" opts keyval))] |
11 | 11 | (pr-sequential-writer writer pr-pair "#tailrecursion.priority-map {" ", " "}" opts coll))) |
12 | 12 |
|
13 | 13 | IWithMeta |
14 | 14 | (-with-meta [this meta] |
15 | | - (PersistentPriorityMap. priority->set-of-items item->priority meta __hash)) |
| 15 | + (PersistentPriorityMap. priority->set-of-items item->priority meta keyfn __hash)) |
16 | 16 |
|
17 | 17 | IMeta |
18 | 18 | (-meta [this] meta) |
|
38 | 38 |
|
39 | 39 | ISeqable |
40 | 40 | (-seq [this] |
41 | | - (seq (for [[priority item-set] priority->set-of-items, item item-set] |
42 | | - [item priority]))) |
| 41 | + (if keyfn |
| 42 | + (seq (for [[priority item-set] priority->set-of-items, item item-set] |
| 43 | + [item (item->priority item)])) |
| 44 | + (seq (for [[priority item-set] priority->set-of-items, item item-set] |
| 45 | + [item priority])))) |
43 | 46 |
|
44 | 47 | IReversible |
45 | 48 | (-rseq [coll] |
46 | | - (seq (for [[priority item-set] (rseq priority->set-of-items), item item-set] |
47 | | - [item priority]))) |
| 49 | + (if keyfn |
| 50 | + (seq (for [[priority item-set] (rseq priority->set-of-items), item item-set] |
| 51 | + [item (item->priority item)])) |
| 52 | + (seq (for [[priority item-set] (rseq priority->set-of-items), item item-set] |
| 53 | + [item priority])))) |
48 | 54 |
|
49 | 55 | ICounted |
50 | 56 | (-count [this] |
|
59 | 65 | IStack |
60 | 66 | (-peek [this] |
61 | 67 | (when-not (zero? (count item->priority)) |
62 | | - (let [f (first priority->set-of-items)] |
63 | | - [(first (val f)) (key f)]))) |
| 68 | + (let [f (first priority->set-of-items) |
| 69 | + item (first (val f))] |
| 70 | + (if keyfn |
| 71 | + [item (item->priority item)] |
| 72 | + [item (key f)])))) |
64 | 73 | (-pop [this] |
65 | 74 | (if (zero? (count item->priority)) |
66 | 75 | (throw (js/Error. "Can't pop empty priority map")) |
67 | 76 | (let [f (first priority->set-of-items) |
68 | 77 | item-set (val f) |
69 | 78 | item (first item-set) |
70 | | - priority (key f)] |
| 79 | + priority-key (key f)] |
71 | 80 | (if (= (count item-set) 1) |
72 | 81 | (PersistentPriorityMap. |
73 | | - (dissoc priority->set-of-items priority) |
| 82 | + (dissoc priority->set-of-items priority-key) |
74 | 83 | (dissoc item->priority item) |
75 | 84 | meta |
| 85 | + keyfn |
76 | 86 | nil) |
77 | 87 | (PersistentPriorityMap. |
78 | | - (assoc priority->set-of-items priority (disj item-set item)), |
| 88 | + (assoc priority->set-of-items priority-key (disj item-set item)), |
79 | 89 | (dissoc item->priority item) |
80 | 90 | meta |
| 91 | + keyfn |
81 | 92 | nil))))) |
82 | 93 |
|
83 | 94 | IAssociative |
84 | 95 | (-assoc [this item priority] |
85 | 96 | (if-let [current-priority (get item->priority item nil)] |
86 | 97 | (if (= current-priority priority) |
87 | 98 | this |
88 | | - (let [item-set (get priority->set-of-items current-priority)] |
| 99 | + (let [priority-key (keyfn priority) |
| 100 | + current-priority-key (keyfn current-priority) |
| 101 | + item-set (get priority->set-of-items current-priority-key)] |
89 | 102 | (if (= (count item-set) 1) |
90 | 103 | (PersistentPriorityMap. |
91 | | - (assoc (dissoc priority->set-of-items current-priority) |
92 | | - priority (conj (get priority->set-of-items priority #{}) item)) |
| 104 | + (assoc (dissoc priority->set-of-items current-priority-key) |
| 105 | + priority-key (conj (get priority->set-of-items priority-key #{}) item)) |
93 | 106 | (assoc item->priority item priority) |
94 | 107 | meta |
| 108 | + keyfn |
95 | 109 | nil) |
96 | 110 | (PersistentPriorityMap. |
97 | 111 | (assoc priority->set-of-items |
98 | | - current-priority (disj (get priority->set-of-items current-priority) item) |
99 | | - priority (conj (get priority->set-of-items priority #{}) item)) |
| 112 | + current-priority (disj (get priority->set-of-items current-priority-key) item) |
| 113 | + priority (conj (get priority->set-of-items priority-key #{}) item)) |
100 | 114 | (assoc item->priority item priority) |
101 | 115 | meta |
| 116 | + keyfn |
102 | 117 | nil)))) |
103 | | - (PersistentPriorityMap. |
104 | | - (assoc priority->set-of-items |
105 | | - priority (conj (get priority->set-of-items priority #{}) item)) |
106 | | - (assoc item->priority item priority) |
107 | | - meta |
108 | | - nil))) |
| 118 | + (let [priority-key (keyfn priority)] |
| 119 | + (PersistentPriorityMap. |
| 120 | + (assoc priority->set-of-items |
| 121 | + priority-key (conj (get priority->set-of-items priority-key #{}) item)) |
| 122 | + (assoc item->priority item priority) |
| 123 | + meta |
| 124 | + keyfn |
| 125 | + nil)))) |
109 | 126 |
|
110 | 127 | (-contains-key? [this item] |
111 | 128 | (contains? item->priority item)) |
|
115 | 132 | (let [priority (item->priority item ::not-found)] |
116 | 133 | (if (= priority ::not-found) |
117 | 134 | this |
118 | | - (let [item-set (priority->set-of-items priority)] |
| 135 | + (let [priority-key (keyfn priority) |
| 136 | + item-set (priority->set-of-items priority-key)] |
119 | 137 | (if (= (count item-set) 1) |
120 | 138 | (PersistentPriorityMap. |
121 | | - (dissoc priority->set-of-items priority) |
| 139 | + (dissoc priority->set-of-items priority-key) |
122 | 140 | (dissoc item->priority item) |
123 | 141 | meta |
| 142 | + keyfn |
124 | 143 | nil) |
125 | 144 | (PersistentPriorityMap. |
126 | | - (assoc priority->set-of-items priority (disj item-set item)), |
| 145 | + (assoc priority->set-of-items priority-key (disj item-set item)), |
127 | 146 | (dissoc item->priority item) |
128 | 147 | meta |
| 148 | + keyfn |
129 | 149 | nil)))))) |
130 | 150 |
|
131 | 151 | ISorted |
|
135 | 155 | (let [sets (if ascending? |
136 | 156 | (subseq priority->set-of-items >= k) |
137 | 157 | (rsubseq priority->set-of-items <= k))] |
138 | | - (seq (for [[priority item-set] sets, item item-set] |
139 | | - [item priority])))) |
| 158 | + (if keyfn |
| 159 | + (seq (for [[priority item-set] sets, item item-set] |
| 160 | + [item (item->priority item)])) |
| 161 | + (seq (for [[priority item-set] sets, item item-set] |
| 162 | + [item priority]))))) |
140 | 163 | (-entry-key [this entry] |
141 | | - (val entry)) |
| 164 | + (keyfn (val entry))) |
142 | 165 | (-comparator [this] compare) |
143 | 166 |
|
144 | 167 | IFn |
|
148 | 171 | (-lookup this item not-found))) |
149 | 172 |
|
150 | 173 | (set! tailrecursion.priority-map.PersistentPriorityMap.EMPTY |
151 | | - (PersistentPriorityMap. (sorted-map) {} {} nil)) |
| 174 | + (PersistentPriorityMap. (sorted-map) {} {} identity nil)) |
152 | 175 |
|
153 | 176 | (defn- pm-empty-by [comparator] |
154 | | - (PersistentPriorityMap. (sorted-map-by comparator) {} {} nil)) |
| 177 | + (PersistentPriorityMap. (sorted-map-by comparator) {} {} identity nil)) |
| 178 | + |
| 179 | +(defn- pm-empty-keyfn |
| 180 | + ([keyfn] (PersistentPriorityMap. (sorted-map) {} {} keyfn nil)) |
| 181 | + ([keyfn comparator] (PersistentPriorityMap. (sorted-map-by comparator) {} {} keyfn nil))) |
155 | 182 |
|
156 | 183 | (defn- read-priority-map [elems] |
157 | 184 | (if (map? elems) |
|
178 | 205 | (if in |
179 | 206 | (recur (nnext in) (assoc out (first in) (second in))) |
180 | 207 | out)))) |
| 208 | + |
| 209 | +(defn priority-map-keyfn |
| 210 | + "keyval => key val |
| 211 | + Returns a new priority map with supplied |
| 212 | + mappings, using the supplied keyfn." |
| 213 | + ([keyfn & keyvals] |
| 214 | + (loop [in (seq keyvals) out (pm-empty-keyfn keyfn)] |
| 215 | + (if in |
| 216 | + (recur (nnext in) (assoc out (first in) (second in))) |
| 217 | + out)))) |
| 218 | + |
| 219 | +(defn priority-map-keyfn-by |
| 220 | + "keyval => key val |
| 221 | + Returns a new priority map with supplied |
| 222 | + mappings, using the supplied keyfn and comparator." |
| 223 | + ([keyfn comparator & keyvals] |
| 224 | + (loop [in (seq keyvals) out (pm-empty-keyfn keyfn comparator)] |
| 225 | + (if in |
| 226 | + (recur (nnext in) (assoc out (first in) (second in))) |
| 227 | + out)))) |
0 commit comments