Created
September 7, 2017 19:39
-
-
Save Kah0ona/789d2daf0cae1a9773f0a652272723b5 to your computer and use it in GitHub Desktop.
Transducer that merges consecutive elements if they are similar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(declare merge-peak-with-first) | |
(defn concatenate-similar-peaks-xf [] | |
(fn [xf] | |
(let [prev (volatile! ::none)] | |
(fn | |
([] (xf)) | |
([result] (xf result)) | |
([result input] | |
(let [prior @prev] | |
(vreset! prev input) | |
(if (= (:type prior) (:type input)) | |
;;same type, merge the two peak-maps prior and input, | |
;;else, keep processing | |
(-> result | |
pop ;; <-- !!! pop and conj are too specific functions that deal on collections. | |
;; What should I do to make this work? | |
(conj (merge-peak-with-first prior input))) | |
(xf result input)))))))) | |
(defn merge-peak-with-first | |
"Merges two peaks, the result will retain the values of p1 but: | |
- :end_time will be become the value of p2 | |
- :peak will be the concat' value of p1 and p2" | |
[p1 p2] | |
(-> p1 | |
(update :peak | |
(fn [p1-peak new-peak] | |
(vec (concat p1-peak new-peak))) | |
(:peak p2)) | |
(update :end-time | |
(fn [_ new-end-time] new-end-time) | |
(:end-time p2)))) | |
;; Usage below | |
;; =========== | |
(def test-peaks | |
[{:type :a | |
:peak [1 2] | |
:end_time 1} | |
{:type :a | |
:peak [3 4] | |
:end_time 2} | |
{:type :a | |
:peak [5 6] | |
:end_time 3} | |
{:type :b | |
:peak [] | |
:end_time 8]) | |
;; I want the result to be: | |
;; [{:type :a :peak [1 2 3 4 5 6] :end_time 3} | |
;; {:type :b :peak [] :end_time 8}] | |
(into [] (concatenate-similar-peaks-xf) test-peaks) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment