Added continuous-subseqs navigator

This commit is contained in:
Nathan Marz 2016-05-28 13:57:30 -04:00
parent 009a9c93f6
commit e2e8fa091e
4 changed files with 63 additions and 0 deletions

View file

@ -7,9 +7,11 @@
* BREAKING CHANGE: `path` renamed to `nav` * BREAKING CHANGE: `path` renamed to `nav`
* BREAKING CHANGE: `fixed-pathed-path` and `variable-pathed-path` renamed to `fixed-pathed-nav` and `variabled-pathed-nav` * BREAKING CHANGE: `fixed-pathed-path` and `variable-pathed-path` renamed to `fixed-pathed-nav` and `variabled-pathed-nav`
* Added `must` navigator to navigate to a key if and only if it exists in the structure * Added `must` navigator to navigate to a key if and only if it exists in the structure
* Added `continous-subseqs` navigator
* Added `ATOM` navigator (thanks @rakeshp) * Added `ATOM` navigator (thanks @rakeshp)
* Added "navigator constructors" that can be defined via `defnavconstructor`. These allow defining a flexible function to parameterize a defnav, and the function integrates with inline caching for high performance. * Added "navigator constructors" that can be defined via `defnavconstructor`. These allow defining a flexible function to parameterize a defnav, and the function integrates with inline caching for high performance.
## 0.10.0 ## 0.10.0
* Make codebase bootstrap cljs compatible * Make codebase bootstrap cljs compatible
* Remove usage of reducers in cljs version in favor of transducers (thanks @StephenRudolph) * Remove usage of reducers in cljs version in favor of transducers (thanks @StephenRudolph)

View file

@ -181,6 +181,24 @@
(i/srange-transform structure start end next-fn) (i/srange-transform structure start end next-fn)
)) ))
(defnav
^{:doc "Navigates to every continuous subsequence of elements matching `pred`"}
continuous-subseqs
[pred]
(select* [this structure next-fn]
(doall
(mapcat
(fn [[s e]] (i/srange-select structure s e next-fn))
(i/matching-ranges structure pred)
)))
(transform* [this structure next-fn]
(reduce
(fn [structure [s e]]
(i/srange-transform structure s e next-fn))
structure
(reverse (i/matching-ranges structure pred))
)))
(def BEGINNING (srange 0 0)) (def BEGINNING (srange 0 0))
(def END (srange-dynamic count count)) (def END (srange-dynamic count count))

View file

@ -575,6 +575,27 @@
res res
))) )))
(defn- matching-indices [aseq p]
(keep-indexed (fn [i e] (if (p e) i)) aseq))
(defn matching-ranges [aseq p]
(first
(reduce
(fn [[ranges curr-start curr-last :as curr] i]
(cond
(nil? curr-start)
[ranges i i]
(= i (inc curr-last))
[ranges curr-start i]
:else
[(conj ranges [curr-start (inc curr-last)]) i i]
))
[[] nil nil]
(concat (matching-indices aseq p) [-1])
)))
(extend-protocol p/Navigator (extend-protocol p/Navigator
nil nil
(select* [this structure next-fn] (select* [this structure next-fn]

View file

@ -969,3 +969,25 @@
:a :a
)))) ))))
) )
(defspec continuous-subseqs-filter-equivalence
(for-all+
[aseq (gen/vector (gen/elements [1 2 3 :a :b :c 4 5 :d :e]))
pred (gen/elements [keyword? number?])]
(= (setval (s/continuous-subseqs pred) nil aseq)
(filter (complement pred) aseq))
))
(deftest continuous-subseqs-test
(is (= [1 "ab" 2 3 "c" 4 "def"]
(transform
(s/continuous-subseqs string?)
(fn [s] [(apply str s)])
[1 "a" "b" 2 3 "c" 4 "d" "e" "f"]
)))
(is (= [[] [2] [4 6]]
(select
[(s/continuous-subseqs number?) (s/filterer even?)]
[1 "a" "b" 2 3 "c" 4 5 6 "d" "e" "f"]
)))
)