why not just accumulate the interested customers in a set rather than a seq
in the first place?

On Tue, Mar 24, 2015 at 2:50 PM, Simon Brooke <still...@googlemail.com>
wrote:

> I'm rewriting a very odd e-commerce website I first wrote in 1996, for a
> friend.
>
> The website features categories, which are supposed to be arranged into an
> acyclic directed graph (actually there are currently cycles in the graph,
> but there shouldn't be, and that is not the problem I'm trying to solve
> here; assume there are not). Customers can register interest in a category
> or in several categories. When an item is added to the site, we want to
> email every customer who may be interested in that item; which is to say
>
> customers who are interested in the category to which the item has been
> added, and
> customers who are interested in the parent of that category, and
> so on recursively to the root of the graph.
>
> Now, I can recurse up the graph asking each category in turn for the
> customers interested in it; and by concatenating the lists, arrive at one
> list of all the interested customers. The problem is that if one customer
> has registered interest in both a category and its parent, he will appear
> on the composite list twice. I need to construct from this a list of
> records in which each customer appears only once, otherwise they'll receive
> duplicate emails, which no-one likes.
>
> My solution, which I give below, is to recurse across the composite list
> constructing a map whose keys are email addresses and whose values are the
> customer records as maps; and then to take the values of that map. It
> works, but it doesn't feel like idiomatic clojure:
>
> (defn map-by-key
>   "From this `list-of-maps`, produce a map keyed on the values for this
> `key`"
>   [list-of-maps key]
>   (if (empty? list-of-maps) {}
>     (let [record (first list-of-maps)]
>       (merge {(record key) record} (map-by-key (rest list-of-maps) key)))))
>
>
> (defn interested-customers
>   "Return a list of the customers interested in the category with this
>    `category-id`. Recurses up the tree of categories; `path` is passed to
>    protect against cycles in the tree (which shouldn't be there by are
>    not impossible)"
>   ([category-id]
>    (vals (map-by-key (interested-customers category-id #{}) :email)))
>   ([category-id path]
>    (if (contains? path category-id) ()
>     (let
>       [id (if (integer? category-id) category-id
>             (Integer/valueOf (str category-id)))
>        category (categories/fetch id)
>        parent (:parent category)
>        upstream (if (not (nil? parent)) (interested-customers parent (conj
> path id)) ())
>        interested (select schema/customer
>                           (with schema/category
>                             (where {:id id})))]
>       (concat interested upstream)))))
>
> Can anyone re-express that in a more idiomatic form?
>
> --
> 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
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>



-- 
Ben Wolfson
"Human kind has used its intelligence to vary the flavour of drinks, which
may be sweet, aromatic, fermented or spirit-based. ... Family and social
life also offer numerous other occasions to consume drinks for pleasure."
[Larousse, "Drink" entry]

-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to