On Nov 8, 12:33 pm, Michael Jaaka <[email protected]>
wrote:
>
> 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)
<snip>
> Note that all must be evaluated lazily.
Unless the keys in your sequence will always be sorted, I don't
believe you can do this lazily; in order to generate a sequence of the
values for a given key in your collection, you would have to traverse
the entire collection first in order to check each key, i.e. if you
had:
[[ "tom" 32 ] [ "anne" 12 ] [ "anne" 55 ] [ "tom" 2333 ]]
Then you'd need to get right to the end of the list in order to
generate the sequence of values for "tom".
One, non-lazy, way to accomplish what you're after would be:
(use '[clojure.contrib.seq-utils :only (group-by)])
(def *s* [["tom" 32] ["tom" 2333] ["anne" 12] ["anne" 55]])
(defn callback-listener
[k v]
(println (str "key: " k ", value: " v)))
(doseq [[k v] (map (fn [[k v]] [k (map second v)])
(group-by first *s*))]
(callback-listener k v))
Note that since you used the name "callback-listener", I'm assuming
that it has side effects, which is why I used doseq. If callback-
listener does _not_ have side effects (i.e. if it performs some
computation upon it's arguments and simply yields a result, then you
could use:
(defn callback-fn
[[k v]]
(compute-some-value-from-arguments k v))
(map (comp callback-fn (fn [[k v]] [k (map second v)]))
(group-by first *s*))
which would yield a sequence of the result of each call to callback-
fn2. Note that while the resulting sequence would, technically, be
lazy, group-by is not, so you would still consume the entire input
sequence up front.
Now, _if_ you can guarantee that your input sequence will always be
sorted by key (that is, if you know for a fact that all the entries
for a given key will be consecutive, as in your example: [tom tom anne
anne], rather than mine above: [tom anne tom anne]), then you could
use partition-by instead, which would (I believe) let you achieve full
laziness:
(use '[clojure.contrib.seq-utils :only (partition-by)])
(map (comp callback-fn (fn [part] [(ffirst part) (map second part)]))
(partition-by first *s*))
Hope this helps,
-David
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---