This is sweet. Thanks a lot Linus and Alex. So there is no function to do it, you just have to build it yourself. I was not sure of that.
I like Alex's solution. This is something I can read and understand. Also, it would be nice to compare and split in one loop. This is what I came up with, based on Alex's work: (defn partition-by-seq [sub-seq coll] (letfn [(take-sub-seq [coll] (loop [[fcoll & rcoll] (seq coll) [fsub & rsub] (seq sub-seq)] (if (= fcoll fsub) (if (nil? rsub) [sub-seq rcoll] (if rcoll (recur rcoll rsub) [nil coll])) [nil coll]))) (step [coll] (loop [run [] coll (seq coll)] (let [[match more] (take-sub-seq coll)] (if match (if (seq run) (cons run (cons match (lazy-seq (step more)))) (cons match (lazy-seq (step more)))) (if (seq coll) (recur (conj run (first coll)) (drop 1 coll)) (when (seq run) [run]) )))))] (if (seq sub-seq) (step coll) [coll]))) ;; Case: empty sub-seq (= (partition-by-seq [] [:a]) '([:a])) ;; Case: empty coll (= (partition-by-seq [:b :c] []) nil) ;; 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: non-matched remainder (= (partition-by-seq [:b :c] [:a :b :c :b]) '([:a] [:b :c] [:b])) ;; Case: handle nil gracefully (= (partition-by-seq [:b nil nil] [:a :b nil nil :c :b]) '([:a] [:b nil nil] [:c :b])) On Sun, Jun 8, 2014 at 6:27 PM, Alex Walker <alex.wal...@answers.com> wrote: > https://gist.github.com/alexpw/f20c7b3ac858003e07e2 > > This version supports the missing case: > > ;; 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))) > > > On Sunday, June 8, 2014 8:52:09 AM UTC-5, Alex Walker wrote: >> >> Err, this was bugging me all day when I went afk. I wrote it too quickly >> and am missing the case where the sub-seq starts right after seeing the >> first val, [:b :b :c]. >> >> Will fix it if I have time today, but may need to take a slightly >> different approach. Fun problem, btw. :) >> >> On Saturday, June 7, 2014 2:31:04 PM UTC-5, Alex Walker wrote: >>> >>> Here's a solution based on your description that behaves like core >>> partition fns, taking liberty to presume your example should've matched the >>> output below. >>> >>> (defn partition-by-seq >>> [sub-seq coll] >>> (letfn [(step [coll] >>> (when-let [coll (seq coll)] >>> (let [[run more] (split-with (partial not= (first sub-seq)) >>> coll) >>> [possible-match more] (split-at (count sub-seq) more)] >>> (if (= possible-match sub-seq) >>> (if (seq run) >>> (cons run (cons possible-match (lazy-seq (step >>> more)))) >>> (cons possible-match (lazy-seq (step >>> more)))) >>> (cons (concat run possible-match) (lazy-seq (step >>> more)))))))] >>> (or (step coll) ()))) >>> >>> => (partition-by-seq [:b :c] []) >>> >>> () >>> >>> => (partition-by-seq [:b :c] [:a :d]) >>> >>> ((:a :d)) >>> >>> => (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)) >>> >>> >>> >>> On Tuesday, June 3, 2014 4:05:16 AM UTC-5, Ulrich Küttler wrote: >>>> >>>> Hi, >>>> >>>> what is the preferred way to find sub-seqs in a seq? I am trying to >>>> convert >>>> >>>> [:a :b :c :d :a :b :c :d :a :b :c] >>>> >>>> into >>>> >>>> ((:a) (:b :c) (:a :d) (:b :c) (:a)) >>>> >>>> using the sub-seq (:b :c) instead of positions. >>>> >>>> partition, partition-by and the like all look at one element at a time. >>>> What I need is a search based on seqs. Are there functions that support >>>> such a search / split? >>>> >>>> Uli >>>> >>> -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.