add specialized MAP-KEYS navigator
This commit is contained in:
parent
cdbbd13939
commit
2504b7849a
3 changed files with 95 additions and 5 deletions
|
|
@ -650,6 +650,16 @@
|
|||
(transform* [this structure next-fn]
|
||||
(n/map-vals-transform structure next-fn)))
|
||||
|
||||
(defnav
|
||||
^{:doc "Navigate to each key of the map. This is more efficient than
|
||||
navigating via [ALL FIRST]"}
|
||||
MAP-KEYS
|
||||
[]
|
||||
(select* [this structure next-fn]
|
||||
(doseqres NONE [k (keys structure)]
|
||||
(next-fn k)))
|
||||
(transform* [this structure next-fn]
|
||||
(n/map-keys-transform structure next-fn)))
|
||||
|
||||
|
||||
(defcollector VAL []
|
||||
|
|
|
|||
|
|
@ -210,8 +210,12 @@
|
|||
|
||||
|
||||
|
||||
(defprotocol MapValsTransformProtocol
|
||||
(map-vals-transform [structure next-fn]))
|
||||
(defprotocol MapTransformProtocol
|
||||
(map-vals-transform [structure next-fn])
|
||||
(map-keys-transform [structure next-fn])
|
||||
)
|
||||
|
||||
|
||||
|
||||
(defn map-vals-non-transient-transform [structure empty-map next-fn]
|
||||
(reduce-kv
|
||||
|
|
@ -223,10 +227,22 @@
|
|||
empty-map
|
||||
structure))
|
||||
|
||||
(extend-protocol MapValsTransformProtocol
|
||||
(defn map-keys-non-transient-transform [structure empty-map next-fn]
|
||||
(reduce-kv
|
||||
(fn [m k v]
|
||||
(let [newk (next-fn k)]
|
||||
(if (identical? newk i/NONE)
|
||||
m
|
||||
(assoc m newk v))))
|
||||
empty-map
|
||||
structure))
|
||||
|
||||
(extend-protocol MapTransformProtocol
|
||||
nil
|
||||
(map-vals-transform [structure next-fn]
|
||||
nil)
|
||||
(map-keys-transform [structure next-fn]
|
||||
nil)
|
||||
|
||||
|
||||
#?(:clj clojure.lang.PersistentArrayMap)
|
||||
|
|
@ -257,17 +273,48 @@
|
|||
array
|
||||
)]
|
||||
(clojure.lang.PersistentArrayMap. array)))))
|
||||
|
||||
#?(:clj
|
||||
(map-keys-transform [structure next-fn]
|
||||
(let [k-it (.keyIterator structure)
|
||||
v-it (.valIterator structure)
|
||||
none-cell (i/mutable-cell 0)
|
||||
len (.count structure)
|
||||
array (i/fast-object-array (* 2 len))]
|
||||
(loop [i 0
|
||||
j 0]
|
||||
(if (.hasNext k-it)
|
||||
(let [k (.next k-it)
|
||||
v (.next v-it)
|
||||
newk (next-fn k)]
|
||||
(if (identical? newk i/NONE)
|
||||
(do
|
||||
(i/update-cell! none-cell inc)
|
||||
(recur (+ i 2) j))
|
||||
(do
|
||||
(aset array j newk)
|
||||
(aset array (inc j) v)
|
||||
(recur (+ i 2) (+ j 2)))))))
|
||||
(let [none-count (i/get-cell none-cell)
|
||||
array (if (not= 0 none-count)
|
||||
(java.util.Arrays/copyOf array (int (* 2 (- len none-count))))
|
||||
array
|
||||
)]
|
||||
(clojure.lang.PersistentArrayMap/createAsIfByAssoc array)))))
|
||||
|
||||
#?(:cljs cljs.core/PersistentArrayMap)
|
||||
#?(:cljs
|
||||
(map-vals-transform [structure next-fn]
|
||||
(map-vals-non-transient-transform structure {} next-fn)))
|
||||
#?(:cljs
|
||||
(map-keys-transform [structure next-fn]
|
||||
(map-keys-non-transient-transform structure {} next-fn)))
|
||||
|
||||
|
||||
#?(:clj clojure.lang.PersistentTreeMap :cljs cljs.core/PersistentTreeMap)
|
||||
(map-vals-transform [structure next-fn]
|
||||
(map-vals-non-transient-transform structure (empty structure) next-fn))
|
||||
(map-keys-transform [structure next-fn]
|
||||
(map-keys-non-transient-transform structure (empty structure) next-fn))
|
||||
|
||||
|
||||
#?(:clj clojure.lang.PersistentHashMap :cljs cljs.core/PersistentHashMap)
|
||||
|
|
@ -283,7 +330,18 @@
|
|||
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY))
|
||||
|
||||
structure)))
|
||||
(map-keys-transform [structure next-fn]
|
||||
(persistent!
|
||||
(reduce-kv
|
||||
(fn [m k v]
|
||||
(let [newk (next-fn k)]
|
||||
(if (identical? newk i/NONE)
|
||||
m
|
||||
(assoc! m newk v))))
|
||||
(transient
|
||||
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY))
|
||||
|
||||
structure)))
|
||||
|
||||
#?(:clj Object :cljs default)
|
||||
(map-vals-transform [structure next-fn]
|
||||
|
|
@ -294,9 +352,17 @@
|
|||
m
|
||||
(assoc m k newv))))
|
||||
(empty structure)
|
||||
structure))
|
||||
(map-keys-transform [structure next-fn]
|
||||
(reduce-kv
|
||||
(fn [m k v]
|
||||
(let [newk (next-fn k)]
|
||||
(if (identical? newk i/NONE)
|
||||
m
|
||||
(assoc m newk v))))
|
||||
(empty structure)
|
||||
structure)))
|
||||
|
||||
|
||||
(defn srange-select [structure start end next-fn]
|
||||
(next-fn
|
||||
(if (string? structure)
|
||||
|
|
|
|||
|
|
@ -1455,3 +1455,17 @@
|
|||
(is (predand= vector? [1 0] (setval s/AFTER-ELEM 0 v)))
|
||||
(is (predand= vector? [1 0] (setval (s/srange 1 1) [0] v)))
|
||||
))
|
||||
|
||||
(defspec map-keys-all-first-equivalence-transform
|
||||
(for-all+
|
||||
[m (limit-size 10 (gen/map gen/int gen/keyword))]
|
||||
(= (transform s/MAP-KEYS inc m)
|
||||
(transform [s/ALL s/FIRST] inc m )
|
||||
)))
|
||||
|
||||
(defspec map-keys-all-first-equivalence-select
|
||||
(for-all+
|
||||
[m (limit-size 10 (gen/map gen/int gen/keyword))]
|
||||
(= (select s/MAP-KEYS m)
|
||||
(select [s/ALL s/FIRST] m)
|
||||
)))
|
||||
|
|
|
|||
Loading…
Reference in a new issue