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]
|
(transform* [this structure next-fn]
|
||||||
(n/map-vals-transform 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 []
|
(defcollector VAL []
|
||||||
|
|
|
||||||
|
|
@ -210,8 +210,12 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defprotocol MapValsTransformProtocol
|
(defprotocol MapTransformProtocol
|
||||||
(map-vals-transform [structure next-fn]))
|
(map-vals-transform [structure next-fn])
|
||||||
|
(map-keys-transform [structure next-fn])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn map-vals-non-transient-transform [structure empty-map next-fn]
|
(defn map-vals-non-transient-transform [structure empty-map next-fn]
|
||||||
(reduce-kv
|
(reduce-kv
|
||||||
|
|
@ -223,10 +227,22 @@
|
||||||
empty-map
|
empty-map
|
||||||
structure))
|
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
|
nil
|
||||||
(map-vals-transform [structure next-fn]
|
(map-vals-transform [structure next-fn]
|
||||||
nil)
|
nil)
|
||||||
|
(map-keys-transform [structure next-fn]
|
||||||
|
nil)
|
||||||
|
|
||||||
|
|
||||||
#?(:clj clojure.lang.PersistentArrayMap)
|
#?(:clj clojure.lang.PersistentArrayMap)
|
||||||
|
|
@ -257,17 +273,48 @@
|
||||||
array
|
array
|
||||||
)]
|
)]
|
||||||
(clojure.lang.PersistentArrayMap. 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 cljs.core/PersistentArrayMap)
|
||||||
#?(:cljs
|
#?(:cljs
|
||||||
(map-vals-transform [structure next-fn]
|
(map-vals-transform [structure next-fn]
|
||||||
(map-vals-non-transient-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)
|
#?(:clj clojure.lang.PersistentTreeMap :cljs cljs.core/PersistentTreeMap)
|
||||||
(map-vals-transform [structure next-fn]
|
(map-vals-transform [structure next-fn]
|
||||||
(map-vals-non-transient-transform structure (empty 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)
|
#?(:clj clojure.lang.PersistentHashMap :cljs cljs.core/PersistentHashMap)
|
||||||
|
|
@ -283,7 +330,18 @@
|
||||||
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY))
|
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY))
|
||||||
|
|
||||||
structure)))
|
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)
|
#?(:clj Object :cljs default)
|
||||||
(map-vals-transform [structure next-fn]
|
(map-vals-transform [structure next-fn]
|
||||||
|
|
@ -294,9 +352,17 @@
|
||||||
m
|
m
|
||||||
(assoc m k newv))))
|
(assoc m k newv))))
|
||||||
(empty structure)
|
(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)))
|
structure)))
|
||||||
|
|
||||||
|
|
||||||
(defn srange-select [structure start end next-fn]
|
(defn srange-select [structure start end next-fn]
|
||||||
(next-fn
|
(next-fn
|
||||||
(if (string? structure)
|
(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/AFTER-ELEM 0 v)))
|
||||||
(is (predand= vector? [1 0] (setval (s/srange 1 1) [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