consolidate overlapping ranges
transduce over the ordered range values starts and ends and do the stack push/pop matching over the start and end values to consolidate the overlapping ranges and result in a new set of consolidated and sorted range values.
This commit is contained in:
@@ -52,3 +52,48 @@
|
||||
:boundary-type :end
|
||||
:type (range-type range)}]))
|
||||
(sort-by (juxt :value (comp {:start 0 :end 1} :boundary-type)))))
|
||||
|
||||
(defmulti ->discrete-value-range (fn [range-type _start _end]
|
||||
range-type))
|
||||
|
||||
(defn combine-overlapping-ranges
|
||||
"transducer to find and combine overlapping ranges by looking at
|
||||
ordered range value markers.
|
||||
|
||||
When it encounters a range's start boundary it pushes an entry on
|
||||
the stack, and captures the value for that start boundary if the
|
||||
stack was previously empty.
|
||||
|
||||
When it encounters a range's end boundary value, it pops an item
|
||||
from the stack, and if the stack is now empty, it uses the value
|
||||
of the range boundary end and the captured start value to create
|
||||
a new range object, which will contain any other range start and
|
||||
end pairs encountered between the new start and end values."
|
||||
[]
|
||||
(fn [xf]
|
||||
(let [stack (volatile! [])
|
||||
start (volatile! nil)]
|
||||
(fn
|
||||
([] (xf))
|
||||
([result] (xf result))
|
||||
([result input]
|
||||
(if (reduced? input)
|
||||
result
|
||||
(case (:boundary-type input)
|
||||
:start (do
|
||||
(when-not (seq @stack)
|
||||
(vreset! start (:value input)))
|
||||
(vswap! stack (fnil conj []) input)
|
||||
result)
|
||||
:end (do
|
||||
(vswap! stack pop)
|
||||
(if (seq @stack)
|
||||
result
|
||||
(xf result (->discrete-value-range (:type input) @start (:value input))))))))))))
|
||||
|
||||
(def consolidate-ranges-xf
|
||||
(comp
|
||||
(combine-overlapping-ranges)))
|
||||
|
||||
(defn consolidate [ranges]
|
||||
(eduction consolidate-ranges-xf (ordered-range-values ranges)))
|
||||
|
||||
Reference in New Issue
Block a user