Skip to content

Instantly share code, notes, and snippets.

@alexpw
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexpw/f20c7b3ac858003e07e2 to your computer and use it in GitHub Desktop.
Save alexpw/f20c7b3ac858003e07e2 to your computer and use it in GitHub Desktop.
partition-by-seq: Search seqs in seq
(defn partition-by-seq
"Partition coll by splitting each time it encounters sub-seq. The sub-seq
can optionally contain fns, just like partition-by."
[sub-seq coll]
(let [cnt-seq (count sub-seq)
match? (if (some fn? sub-seq)
(let [partials (mapv (fn [f]
(if (fn? f)
#(f %)
#(= f %))) sub-seq)]
(fn [possible-match]
(every? true? (map #(% %2) partials possible-match))))
#(= sub-seq %))]
(letfn [(step [run coll]
(if-let [coll (seq coll)]
(let [[possible-match more] (split-at cnt-seq coll)]
(if (match? possible-match)
(if (seq run)
(cons run (cons possible-match (lazy-seq (step () more))))
(cons possible-match (lazy-seq (step () more))))
(let [[after-run before-more] (split-at 1 possible-match)]
(lazy-seq (step (concat run after-run)
(concat before-more more))))))
(if (= () run) () (list run))))]
(step () coll))))
;; Case: empty coll
(= (partition-by-seq [:b :c] []) ())
;; Case: no match
(= (partition-by-seq [:b :c] [:a :d]) '((:a :d)))
;; Case: example input
(= (partition-by-seq [:b :c] [:a :b :c :d :a :b :c :d :a :b :c])
'((:a) (:b :c) (:d :a) (:b :c) (:d :a) (:b :c)))
;; Case: false match :b, followed by true match :b :c
(= (partition-by-seq [:b :c] [:a :b :b :c :e :d :a :b :c :d :a :b :c])
'((:a :b) (:b :c) (:e :d :a) (:b :c) (:d :a) (:b :c)))
;; Case: using a seq of fns instead of values
(= (partition-by-seq [odd? odd? even?] [1 2 3 5 6 7 8 9 11 12])
'((1 2) (3 5 6) (7 8) (9 11 12)))
;; Case: compare using a mix of fns and values
(= (partition-by-seq [odd? 10] [1 10 2 10 3 10 4 10 5 10 6])
'((1 10) (2 10) (3 10) (4 10) (5 10) (6)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment