Dmitry Kakurin wrote:
> I actually like your "tag them then group them" approach.
> But what if the same record can have multiple tags?
> E.g. :sales and :upgrades?
>
Hmmm. the first way that occurred to me is just make your tagging
function return a set:
(defn record-types [x]
(disj
#{(when (is-sale? x) :sales)
(when (is-upgrade? x) :upgrades)
(when (is-demo? x) :demos)}
nil))
So you'd then get groups like:
{#{:sales :upgrades} [...]
#{:sales} [...]
#{:upgrades} [...]}
But unfortunately it seems that because the group-by in
clojure.contrib.seq-utils uses a sorted-map it can't have keys that are
sets (as there's no ordering defined for sets). You could either use
vectors instead of sets, or better yet lets just define reduce-by and
group-by to use a hash-map instead:
(defn reduce-by [grouper f val coll]
(reduce (fn [m x]
(let [group (grouper x)]
(assoc m group (f (get m group val) x))))
{} coll))
(defn group-by [grouper coll]
(reduce-by grouper conj [] coll))
This has the advantage that you can do things like intersections
("number of sales sales that were also upgrades"). If you don't care
about intersections and just want the three :sales, :upgrades, and
:demos lists, then I guess we start with 'for' to generate [tag record]
pairs:
(for [record (get-idata)
type (record-types record)]
[type record])
So if "data1" is both sales and upgrades then you'd get:
([:sales data1] [:upgrades data1] [:sales data2] [:demos data3] ...)
We can then reduce-by grouped on the first value in the pair (the tag)
and then transform the resulting maps to select just the second item in
the pair (the record):
(reduce-by
first #(conj %1 (second %2)) []
(for [record (get-idata)
type (record-types record)]
[type record]))
=> {:sales [data1 data2 ... ],
:upgrades [data1 data3 ...],
:demos [data4 ...]}
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---