ClojureDocs

Nav

Namespaces

intersection

clojure.set

Available since 1.0
  • (intersection s1)
  • (intersection s1 s2)
  • (intersection s1 s2 & sets)
Return a set that is the intersection of the input sets
5 Examples
user=> (clojure.set/intersection #{1})
#{1}
user=> (clojure.set/intersection #{1 2} #{2 3})
#{2}
user=> (clojure.set/intersection #{1 2} #{2 3} #{3 4})
#{}
user=> (clojure.set/intersection #{1 :a} #{:a 3} #{:a})
#{:a}
(defn find-divisors [x]
  (->> (range 1 (inc x))
       (into #{} (filter #(zero? (mod x %))))))

(find-divisors 10)
;; => #{1 2 5 10}

;; Greatest common divisor
(defn gcd [x y]
  (let [x-div (find-divisors x)
        y-div (find-divisors y)]
    (apply max (clojure.set/intersection y-div x-div))))

(gcd 10 5)
;; => 5

;; Lowest common multiple
(defn lcm [x y]
  (/ (Math/abs (* x y)) (gcd x y)))

(lcm 13 11)
;; => 143
(clojure.set/intersection #{:a :b :c} #{:d :c :b})
;=> #{:b :c}

(clojure.set/intersection #{:a :e :i :o :u}
			  #{:a :u :r}
			  #{:r :u :s})
;=> #{:u}
;; Advice: Do not call intersection with non-set arguments.  If you
;; are concerned that you may be unintentionally doing so, and want an
;; exception to be thrown if you do, consider using the library
;; funjible (https://github.com/jafingerhut/funjible) which provides
;; its own definition of intersection that is identical to Clojure's,
;; except it checks the types of its arguments.

;; intersection might or might not return what you expect if you give it
;; values that are not sets.  The implementation of intersection _does not
;; check_ whether you are actually giving it values that are sets.  It
;; _assumes_ so.

;; It is possible that intersection _might_ throw an exception if you
;; give it a non-set as an argument:
user=> (intersection #{1 3 5} [2 4])
ClassCastException clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentSet  clojure.core/disj (core.clj:1517)

;; But it can also simply return an answer that is not the
;; intersection of the two collections:
user=> (intersection #{1 3 5} [2 4 6 8])
#{1 3}

;; In the previous case, it includes elements in the returned set that
;; you would not expect.  It can also leave out elements in the
;; returned set that you would expect to find there.
user=> (intersection #{"1" "3" "5"} ["1" "3" "5" "7"])
#{}

;; Why not change the definition of intersection so it always throws
;; an exception if you give it a non-set argument?  I would guess that
;; the primary reason is that the extra run-time type checks would
;; slow intersection down by an amount that the Clojure core team does
;; not want everyone to have to pay on every such call.

;; Related Clojure tickets: 
;; https://dev.clojure.org/jira/browse/CLJ-1953
;; https://dev.clojure.org/jira/browse/CLJ-2287
;; using clojure.set operations as query optimization:
;; given a vector of map items:

(def data [{:gender "male",   :age-group "child",  :origin "Germany", :prename "Hans"}
	   {:gender "male",   :age-group "adult",  :origin "France",  :prename "Jacques"}
	   {:gender "male",   :age-group "senior", :origin "Estonia", :prename "Rasmus"}
	   {:gender "male",   :age-group "adult",  :origin "Poland",  :prename "Jakub"}
	   {:gender "male",   :age-group "senior", :origin "Germany", :prename "Uwe"}
	   {:gender "female", :age-group "adult",  :origin "France",  :prename "Amélie"}
	   {:gender "female", :age-group "child",  :origin "Estonia", :prename "Sofia"}
	   {:gender "female", :age-group "child",  :origin "Germany", :prename "Emma"}
	   {:gender "female", :age-group "child",  :origin "Estonia", :prename "Alisa"}
	   {:gender "female", :age-group "senior", :origin "Poland",  :prename "Anna"}])

;; we can create key -> "value" -> set of idx pointers 
;; note: (reduce-kv calls aggregator fn with [aggregate index-in-vector value] when using vectors as the key-value collection.

(def db-index
  (reduce-kv
   (fn [db idx item]
     (reduce
      (fn [db index-on]
        (update db index-on update (get item index-on) (fnil conj #{}) idx))    
      db [:gender :age-group :origin :prename]))
   {} data))

;; results in this key - val -> #{indexes} in vector

{:gender    {"male"  #{0 1 4 3 2},
             "female" #{7 6 9 5 8}},
 
 :age-group {"child" #{0 7 6 8},
             "adult"  #{1 3 5},
             "senior" #{4 2 9}},
 
 :origin    {"Germany" #{0 7 4},
             "France" #{1 5},
             "Estonia" #{6 2 8},
             "Poland" #{3 9}},
 
 :prename   {"Sofia" #{6}, "Rasmus" #{2}, "Hans" #{0}, "Amélie" #{5}, "Jakub" #{3},
             "Jacques" #{1}, "Emma" #{7}, "Alisa" #{8}, "Uwe" #{4}, "Anna" #{9}}}

;; by using intersection on two different key-values indexes we get the items
;; with these properties, for instance "find all men from Germany"

(def all-men-from-germany-idxs
  (clojure.set/intersection
   (get-in db-index [:gender "male"])
   (get-in db-index [:origin "Germany"])))

;; 

(map data (sort all-men-from-germany-idxs))
See Also

Return a set that is the union of the input sets

Added by mmwaikar

Return a set that is the first set without elements of the remaining sets

Added by mmwaikar

Is set1 a superset of set2?

Added by mmwaikar

Returns a rel of the elements of xrel with only the keys in ks

Added by boxie
0 Notes
No notes for intersection