Skip to content

Commit 6d4c384

Browse files
committed
add support for priority-map-keyfn and priority-map-keyfn-by
1 parent 2be6066 commit 6d4c384

File tree

2 files changed

+88
-30
lines changed

2 files changed

+88
-30
lines changed

src/cljs/tailrecursion/priority_map.cljs

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
reader-error]])
55
(:require-macros [cljs.core :as coreclj]))
66

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]
88
IPrintWithWriter
99
(-pr-writer [coll writer opts]
1010
(let [pr-pair (fn [keyval] (pr-sequential-writer writer pr-writer "" " " "" opts keyval))]
1111
(pr-sequential-writer writer pr-pair "#tailrecursion.priority-map {" ", " "}" opts coll)))
1212

1313
IWithMeta
1414
(-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))
1616

1717
IMeta
1818
(-meta [this] meta)
@@ -38,13 +38,19 @@
3838

3939
ISeqable
4040
(-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]))))
4346

4447
IReversible
4548
(-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]))))
4854

4955
ICounted
5056
(-count [this]
@@ -59,53 +65,64 @@
5965
IStack
6066
(-peek [this]
6167
(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)]))))
6473
(-pop [this]
6574
(if (zero? (count item->priority))
6675
(throw (js/Error. "Can't pop empty priority map"))
6776
(let [f (first priority->set-of-items)
6877
item-set (val f)
6978
item (first item-set)
70-
priority (key f)]
79+
priority-key (key f)]
7180
(if (= (count item-set) 1)
7281
(PersistentPriorityMap.
73-
(dissoc priority->set-of-items priority)
82+
(dissoc priority->set-of-items priority-key)
7483
(dissoc item->priority item)
7584
meta
85+
keyfn
7686
nil)
7787
(PersistentPriorityMap.
78-
(assoc priority->set-of-items priority (disj item-set item)),
88+
(assoc priority->set-of-items priority-key (disj item-set item)),
7989
(dissoc item->priority item)
8090
meta
91+
keyfn
8192
nil)))))
8293

8394
IAssociative
8495
(-assoc [this item priority]
8596
(if-let [current-priority (get item->priority item nil)]
8697
(if (= current-priority priority)
8798
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)]
89102
(if (= (count item-set) 1)
90103
(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))
93106
(assoc item->priority item priority)
94107
meta
108+
keyfn
95109
nil)
96110
(PersistentPriorityMap.
97111
(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))
100114
(assoc item->priority item priority)
101115
meta
116+
keyfn
102117
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))))
109126

110127
(-contains-key? [this item]
111128
(contains? item->priority item))
@@ -115,17 +132,20 @@
115132
(let [priority (item->priority item ::not-found)]
116133
(if (= priority ::not-found)
117134
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)]
119137
(if (= (count item-set) 1)
120138
(PersistentPriorityMap.
121-
(dissoc priority->set-of-items priority)
139+
(dissoc priority->set-of-items priority-key)
122140
(dissoc item->priority item)
123141
meta
142+
keyfn
124143
nil)
125144
(PersistentPriorityMap.
126-
(assoc priority->set-of-items priority (disj item-set item)),
145+
(assoc priority->set-of-items priority-key (disj item-set item)),
127146
(dissoc item->priority item)
128147
meta
148+
keyfn
129149
nil))))))
130150

131151
ISorted
@@ -135,10 +155,13 @@
135155
(let [sets (if ascending?
136156
(subseq priority->set-of-items >= k)
137157
(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])))))
140163
(-entry-key [this entry]
141-
(val entry))
164+
(keyfn (val entry)))
142165
(-comparator [this] compare)
143166

144167
IFn
@@ -148,10 +171,14 @@
148171
(-lookup this item not-found)))
149172

150173
(set! tailrecursion.priority-map.PersistentPriorityMap.EMPTY
151-
(PersistentPriorityMap. (sorted-map) {} {} nil))
174+
(PersistentPriorityMap. (sorted-map) {} {} identity nil))
152175

153176
(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)))
155182

156183
(defn- read-priority-map [elems]
157184
(if (map? elems)
@@ -178,3 +205,23 @@
178205
(if in
179206
(recur (nnext in) (assoc out (first in) (second in)))
180207
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))))

test/tailrecursion/priority_map/test.cljs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@
6767
(assert (= (subseq p >= 4) '([:e 4] [:d 5])))
6868
(assert (= (subseq p >= 4 < 5) '([:e 4])))
6969

70+
(def pk (pm/priority-map-keyfn :order :a {:order 2} :b {:order 1} :c {:order 3}))
71+
72+
(assert (= (seq pk) [[:b {:order 1}] [:a {:order 2}] [:c {:order 3}]]))
73+
(assert (= (subseq pk > 1) '([:a {:order 2}] [:c {:order 3}])))
74+
(assert (= (rsubseq pk < 3) '([:a {:order 2}] [:b {:order 1}])))
75+
76+
(def pkb (pm/priority-map-keyfn-by :order > :a {:order 2} :b {:order 1} :c {:order 3}))
77+
(assert (= (seq pkb) [[:c {:order 3}] [:a {:order 2}] [:b {:order 1}]]))
78+
(assert (= (rsubseq pkb < 1) '([:a {:order 2}] [:c {:order 3}])))
79+
(assert (= (subseq pkb > 3) '([:a {:order 2}] [:b {:order 1}])))
80+
7081
;;; printing, reader
7182

7283
(assert (= p (read-string (pr-str p))))

0 commit comments

Comments
 (0)