On Oct 27, 3:15 pm, "Bill Clementson" <[EMAIL PROTECTED]> wrote:
> On Mon, Oct 27, 2008 at 11:31 AM, Rich Hickey <[EMAIL PROTECTED]> wrote:
>
> > On Oct 27, 12:04 pm, "Bill Clementson" <[EMAIL PROTECTED]> wrote:
> >> Hi Chouser
>
> >> On Mon, Oct 27, 2008 at 8:46 AM, Chouser <[EMAIL PROTECTED]> wrote:
>
> >> > I think it's generally better to use = instead of .equals for
> >> > equality, unless you have a specific reason to not use = (which I
> >> > don't think is the case here).
>
> >> Only that it allowed me to talk about Java interop in my blog post. ;-)
>
> >> > On Mon, Oct 27, 2008 at 11:12 AM, Stuart Halloway
> >> > <[EMAIL PROTECTED]> wrote:
>
> >> >> You could do something like this:
>
> >> >> (defn seq-xor-2-seqs
> >> >>   "Returns the unique values that are in one sequence but not the
> >> >> other."
> >> >>   [x y]
> >> >>   (let [x (into #{} x)
> >> >>        y (into #{} y)]
> >> >>     (lazy-cat (clojure.set/difference x y)
> >> >>              (clojure.set/difference y x))))
>
> >> >> Not sure this is more idiomatic, though.  And I guess it would perform
> >> >> worse with huge collections...
>
> >> > If I'm reading thing's correctly, Bill's solution is O(n^2), while
> >> > Stuart's is O(n*log(n)) or better.  It looks like difference iterates
> >> > over one seq and for each item does a lookup (nearly constant time) on
> >> > the the other, although copying into sets may use more memory.
>
> >> > By the way, difference is eager, so I'm not sure there's much point in
> >> > using lazy-cat. :-)
>
> >> > Here's another approach to do all the seqs at once:
>
> >> > (defn seq-xor
> >> >  "Returns unique values that are in one sequence but not the others."
> >> >  [& seqs]
> >> >  (let [obj-cnt (reduce (fn [acc s]
> >> >                          (merge-with + acc (into {} (for [i s] {i 1}))))
> >> >                        {} seqs)]
> >> >    (for [[obj cnt] obj-cnt :when (== cnt 1)]
> >> >      obj)))
>
> >> Oooh, very nice!
>
> > Here's a simple one with set ops:
>
> > (alias 'set 'clojure.set)
>
> > (defn set-xor [& sets]
> >  (second (reduce
> >           (fn [[all ret] s]
> >               [(set/union all s) (set/union (set/difference ret s)
> > (set/difference s all))])
> >           [#{} #{}] sets)))
>
> > (defn seq-xor [& seqs] (seq (apply set-xor (map set seqs))))
>
> Yet another clever alternative!
>
> Thanks guys!

One more, inspired by Chouser's, one pass, no counting:

(defn seq-xor [& seqs]
  (seq (second
        (reduce (fn [[all ret] x]
                    (if (contains? all x)
                      [all (disj ret x)]
                      [(conj all x) (conj ret x)]))
                [#{} #{}] (mapcat distinct seqs)))))

One take away from all of these is that use of sets, maps and vectors
is very idiomatic Clojure, and the sooner you can add them to the
lists in your toolbox the more productive you'll be with Clojure.

Thanks so much for the blog series!

Rich
--~--~---------~--~----~------------~-------~--~----~
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
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to