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.

Reply via email to