summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-02-12 01:19:10 +0000
committerRich Hickey <richhickey@gmail.com>2009-02-12 01:19:10 +0000
commit60e805dc7bd42b7b26fc8c8925bf71079729e0e6 (patch)
tree6a2d81487ca2ef509fc1eec7e0b44c29a0b73308
parent57b8c85d080d228f550d40309fa974d5508af93f (diff)
added multi-arg clojure.set/union/difference/intersection, patch from jawolfe
-rw-r--r--src/clj/clojure/set.clj53
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"