Hi, Am 08.11.2009 um 13:33 schrieb Michael Jaaka:
> Hi! How would you solve such problem: > > I have a collection of pairs (key, value) -> > [ [ "tom" 32 ] [ "tom" 2333 ] [ "anne" 12 ] [ "anne" 55 ] ] > > As you can see keys can occur more than once, also that collection > is very large so it should be evaluated lazily (for example the > collection cames from stream input). > > I have function with two arguments key and sequence of its values, > the pseudo code would be: > > callbackListener(string key, iterator values) > > now I would like get such effect that callbackListener will be > called twice for the example collection. > > once with "tom" and iterator (or a lazy seq) to lazy evaluated > collection of (32 and 2333) > and second with "anne" and iterator for collection of (12 and 55) > > In Java it is easy because the language is imperative. But how about > such logic in Clojure? > Note that all must be evaluated lazily. Obviously, this cannot be done completely lazy since changing the first element is not a stopping time. You'll always need at least one lookahead to determine the change of the key and you'll have to realize the input to find all values for a key. (defn grouped-seq [input] (lazy-seq (when-let [s (seq input)] (let [k (ffirst s) [vs r] (split-with #(-> % first (= k)) s)] (cons [k vs] (grouped-seq r)))))) (map #(apply callbackListener %) (grouped-seq [["tom" 32] ["tom" 2333] ["anne" 12] ["anne" 55]])) Note: if you try to avoid realizing all values of a given key, you'll need two sequences: one to keep track of the key and of for the values. While callbackListener realises the values, the key sequence will retain the head of the input causing all values to stay in memory. If you want really laziness, you'll have to traverse the input twice over independent input streams. So if you have a file containing the data, you'll have to read the file twice from independent streams to get full laziness. Sincerely Meikel
smime.p7s
Description: S/MIME cryptographic signature