If we think about what we're doing here is a stateful filter, then maybe we
could leverage a few more core Clojure functions:
(defn distinct-by [f coll]
(let [seen (atom #{})]
(filter (fn [itm]
(let [m (f itm)]
(when-not (@seen m)
(swap! seen conj m))))
coll)))
Now it's true, we're using a atom and a bit of mutability where none
existed before, but personally I think the intent is a bit clearer in this
code. What we're saying is "filter out all results we've seen before". If
this was production code I would probably replace the atom with a
`volatile!` but that's just for (small) performance reasons.
On Sat, Jul 22, 2017 at 7:36 AM, Rob Nikander <[email protected]>
wrote:
> Hi,
>
> Here's a function and a simple use of it. It works, but the code may not
> be good Clojure. I'm wondering how it might be better.
>
> (defn distinct-by
> "Returns a sequence with no repeats of (f item).
> A set is built up internally as the sequence is consumed, so don't use
> it on
> an infinite sequence or you will run out of memory."
> ([f coll]
> (letfn [(get-more [seen input-seq]
> (if (not (empty? input-seq))
> (let [x (first input-seq)
> fx (f x)]
> (if (contains? seen fx)
> (lazy-seq (get-more seen (rest input-seq)))
> (lazy-seq (cons x (get-more (conj seen fx) (rest
> input-seq))))))))]
> (get-more #{} (seq coll)))))
>
> (def xs (list {:n 1, :a 'a} {:n 2, :a 'b} {:n 3, :a 'a} {:n 4, :a 'c} {:n
> 5, :a 'b}))
>
> (distinct-by :a xs)
> => ({:n 1, :a a} {:n 2, :a b} {:n 4, :a c})
>
> Rob
>
> --
> 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
> ---
> 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 [email protected].
> For more options, visit https://groups.google.com/d/optout.
>
--
“One of the main causes of the fall of the Roman Empire was that–lacking
zero–they had no way to indicate successful termination of their C
programs.”
(Robert Firth)
--
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
---
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 [email protected].
For more options, visit https://groups.google.com/d/optout.