Hey thanks :) These are different than partition-by and take-while. partition-by triggers a new partition when the predicate value *changes*, whereas partition-when triggers a new partition at any point in the sequence where the predicate is true. take-while takes all the items up to the point in the sequence where the predicate is true, where take-to-first does the same but *inclusively*, retaining the item at which the predicate first becomes true. I'm not sure but I believe it is not trivial to use partition-by and take-while to implement either of these.
On Mar 17, 10:33 am, Sean Devlin <francoisdev...@gmail.com> wrote: > Hey Greg, welcome to Clojure :) > > You might want to take a look at c.c.seq-utils and the clojure cheat > sheet. Both of these already exist. See take-while & partition-by > > The cheat sheet can be found here:http://clojure.org/cheatsheet > > On Mar 16, 11:12 pm, Greg Fodor <gfo...@gmail.com> wrote: > > > Just saw that I need to sign the contributor agreement. Will do > > promptly. I additionally have implemented two new functions that I > > believe could fit in clojure-contrib.seq and clojure- > > contrib.combinatorics. The seq function partition-at-fenceposts allows > > you to partition a seq based upon bits flipped in an integer value > > passed in, where 1-bits correspond to partition boundaries, the least > > significant bit being earlier fenceposts in the seq. As such, this > > makes it possible to easily implement a function named partitions for > > clojure-contrib.combinatorics, which yields a lazy seq of all possible > > partitions of a seq. > > > user=> (partition-at-fenceposts 1 '(1 2 3 4 5)) > > ((0) (1 2 3 4)) > > > user=> (partition-at-fenceposts 2 '(1 2 3 4 5)) > > ((0 1) (2 3 4)) > > > user=> (partition-at-fenceposts 3 '(1 2 3 4 5)) > > ((0) (1) (2 3 4)) > > > user=> (partitions '(1 2 3)) > > (((0 1 2)) ((0) (1 2)) ((0 1) (2)) ((0) (1) (2))) > > > user=> (partitions '(1 2 3 4 5)) > > (((0 1 2 3 4)) ((0) (1 2 3 4)) ((0 1) (2 3 4)) ((0) (1) (2 3 4)) ((0 1 > > 2) (3 4)) ((0) (1 2) (3 4)) ((0 1) (2) (3 4)) ((0) (1) (2) (3 4)) ((0 > > 1 2 3) (4)) ((0) (1 2 3) (4)) ((0 1) (2 3) (4)) ((0) (1) (2 3) (4)) > > ((0 1 2) (3) (4)) ((0) (1 2) (3) (4)) ((0 1) (2) (3) (4)) ((0) (1) (2) > > (3) (4))) > > > implementation: > > > (defn take-to-first > > "Returns a lazy sequence of successive items from coll up to > > and including the point at which it (pred item) returns true. > > pred must be free of side-effects." > > [pred coll] > > (lazy-seq > > (when-let [s (seq coll)] > > (if-not (pred (first s)) > > (cons (first s) (take-to-first pred (rest s))) > > (list (first s)))))) > > > (defn partition-when > > "Applies f to each value in coll, splitting it each time f returns > > true. Returns a lazy seq of lazy seqs." > > [f coll] > > (when-let [s (seq coll)] > > (lazy-seq > > (let [run (take-to-first f s) > > res (drop (count run) s)] > > (cons run (partition-when f res)))))) > > > (defn partition-at-fenceposts [b coll] > > "Partitions coll at fenceposts corresponding to bits in b that are > > set to 1. Returns a lazy seq of lazy seqs." > > (let [bits b] > > (map #(map first %) > > (partition-when > > (fn [[i v]] (not (zero? (bit-and (bit-shift-left 1 i) > > bits)))) > > (indexed coll))))) > > > (defn partitions [coll] > > "Returns a lazy seq of possible partitions of coll." > > (map #(partition-at-fenceposts % coll) (range (expt 2 (- (count > > coll) 1))))) > > > On Mar 15, 1:24 pm, Greg Fodor <gfo...@gmail.com> wrote: > > > > Hi there, I am just learning Clojure and am processing some BER > > > encoded integer values. Basically, the most significant bit of the > > > integer in the stream indicates the split point between integers, and > > > so I was looking into partition-by to see if that would help. Turns > > > out, what I really need are two complementary functions: take-to-first > > > and partition-when. Take-to-first is similar to take-while, but is > > > *inclusive* and also inverts the boolean. For example: > > > > Clojure=> (take-to-first even? [1 1 1 1]) > > > (1 1 1 1) > > > Clojure=> (take-to-first even? [1 1 1 1 2 3 3 3]) > > > (1 1 1 1 2) > > > Clojure=> (take-to-first even? [2 2 2 ]) > > > (2) > > > > Additionally, partition-when runs through the seq and partitions it on > > > demand when a predicate is true. (Leaving the entry where it is seen > > > to be true in the current partition: > > > > Clojure=> (partition-when even? [1 1 1 2 3 3 3 4 3 3 3 4 3 3 3]) > > > ((1 1 1 2) (3 3 3 4) (3 3 3 4) (3 3 3)) > > > Clojure=> (partition-when even? [1 1 1]) > > > ((1 1 1)) > > > Clojure=> (partition-when even? [1 1 1 2 3 3 3]) > > > ((1 1 1 2) (3 3 3)) > > > Clojure=> (partition-when even? [2 2 2 2]) > > > ((2) (2) (2) (2)) > > > > These seem to sit aside the current take and partitioning functions > > > since they are basically looking at an truth value that indicates a > > > partition or stopping event that we want to capture and cease moving > > > forward. Here is the source: > > > > (defn take-to-first > > > "Returns a lazy sequence of successive items from coll up to > > > and including the point at which it (pred item) returns true. > > > pred must be free of side-effects." > > > [pred coll] > > > (lazy-seq > > > (when-let [s (seq coll)] > > > (if-not (pred (first s)) > > > (cons (first s) (take-to pred (rest s))) > > > (list (first s)))))) > > > > (defn partition-when > > > "Applies f to each value in coll, splitting it each time f returns > > > true. Returns a lazy seq of lazy seqs." > > > [f coll] > > > (when-let [s (seq coll)] > > > (let [run (take-to-first #(f %) s) > > > res (drop (count run) s)] > > > (lazy-seq > > > (cons run (partition-when f res)))))) > > > > I think these could make a good addition to clojure.contrib.seq. > > > Please let me know if there is an easier way to get this in if you > > > agree. Also, please let me know if these are the best ways to write > > > these functions, since I am still a newbie! -- 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