diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-02-12 01:19:10 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-02-12 01:19:10 +0000 |
commit | 60e805dc7bd42b7b26fc8c8925bf71079729e0e6 (patch) | |
tree | 6a2d81487ca2ef509fc1eec7e0b44c29a0b73308 | |
parent | 57b8c85d080d228f550d40309fa974d5508af93f (diff) |
added multi-arg clojure.set/union/difference/intersection, patch from jawolfe
-rw-r--r-- | src/clj/clojure/set.clj | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/src/clj/clojure/set.clj b/src/clj/clojure/set.clj index 32c436e0..87113508 100644 --- a/src/clj/clojure/set.clj +++ b/src/clj/clojure/set.clj @@ -8,20 +8,53 @@ (ns clojure.set) +(defn- bubble-max-key [k coll] + "Move a maximal element of coll according to fn k (which returns a number) + to the front of coll." + (let [max (apply max-key k coll)] + (cons max (remove #(identical? max %) coll)))) + (defn union - "Returns a set that is the union of the two sets." - [xset yset] - (reduce conj xset yset)) + "Return a set that is the union of the input sets" + ([] #{}) + ([s1] s1) + ([s1 s2] + (if (< (count s1) (count s2)) + (reduce conj s2 s1) + (reduce conj s1 s2))) + ([s1 s2 & sets] + (let [bubbled-sets (bubble-max-key count (conj sets s2 s1))] + (reduce into (first bubbled-sets) (rest bubbled-sets))))) + +(defn intersection + "Return a set that is the intersection of the input sets" + ([s1] s1) + ([s1 s2] + (if (< (count s2) (count s1)) + (recur s2 s1) + (reduce (fn [result item] + (if (contains? s2 item) + result + (disj result item))) + s1 s1))) + ([s1 s2 & sets] + (let [bubbled-sets (bubble-max-key #(- (count %)) (conj sets s2 s1))] + (reduce intersection (first bubbled-sets) (rest bubbled-sets))))) (defn difference - "Returns a set that is xset without the elements of yset." - [xset yset] - (reduce disj xset yset)) + "Return a set that is the first set without elements of the remaining sets" + ([s1] s1) + ([s1 s2] + (if (< (count s1) (count s2)) + (reduce (fn [result item] + (if (contains? s2 item) + (disj result item) + result)) + s1 s1) + (reduce disj s1 s2))) + ([s1 s2 & sets] + (reduce difference s1 (conj sets s2)))) -(defn intersection - "Returns a set of the elements present in both xset and yset." - [xset yset] - (difference xset (difference xset yset))) (defn select "Returns a set of the elements for which pred is true" |