The implementation I posted earlier appears to fit the contract of
your partition-before (and, additionally, works properly if the input
starts with (nil ...) :)).

There is another possible variation: partition-dropping. Here the
elements for which pred returns true don't get included in the output
at all; e.g. (partition-dropping #(= 0 (rem % 3)) (range 16)) would
emit ((1 2) (4 5) (7 8) (10 11) (13 14) (16)). The use case for this
is when the pred is testing for a separator sentinel value, an object
in the sequence that you're not actually interested in for any purpose
other than its use as a separator. For instance if you had a text file
of blank-line-delimited paragraphs and wanted a paragraph-seq out of
it, you might use (partition-dropping #(= "" %) (line-seq ...)). Or a
more sophisticated predicate that recognizes all lines with no
nonwhitespace characters as blank:

(defn blank? [s]
  (every? #(Character/isWhitespace %) s))

(partition-dropping blank? (line-seq ...))

And here's an implementation:

(defn partition-dropping [pred coll]
  (let [ipred (complement pred)
        bits (iterate
               (fn [[out coll]]
                 (let [[a b] (split-with ipred (rest coll))
                      x (first coll)]
                   (if (and (seq coll) (pred x))
                     [a b]
                     [(cons x a) b])))
               [nil coll])]
    (map #(first (first %))
      (take-while #(seq (second (second %))) (map vector (rest bits) bits)))))

user=> (partition-dropping #(= 0 (rem % 4)) (range 15))
((1 2 3)
 (5 6 7)
 (9 10 11)
 (13 14))
user=> (take 5 (partition-dropping #(= 0 (rem % 4)) (iterate inc 1)))
((1 2 3)
 (5 6 7)
 (9 10 11)
 (13 14 15)
 (17 18 19))

It handles nils properly:

user=> (partition-dropping identity [nil nil nil true 'x false 1 2
true nil 17 false 4 8 15 16 23 42])
((nil nil nil)
 ()
 (false)
 ()
 ()
 (nil)
 (false)
 ()
 ()
 ()
 ()
 ()
 ())
user=> (partition-dropping (complement identity) [nil nil nil true 'x
false 1 2 true nil 17 false 4 8 15 16 23 42])
(()
 ()
 (true x)
 (1 2 true)
 (17)
 (4 8 15 16 23 42))

though you'll note that empty lists appear whenever pred is true for
two adjacent items. If you want to get rid of those:

user=> (remove empty? (partition-dropping (complement identity) [nil
nil nil true 'x false 1 2 true nil 17 false 4 8 15 16 23 42]))
((true x)
 (1 2 true)
 (17)
 (4 8 15 16 23 42))

-- 
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

Reply via email to