Search

January 8, 2020

Clojure Goodness: Getting Intersections Between Sets

In the clojure.set namespace we can find the intersection function. This functions accepts one or more sets as arguments and return a new set with all elements that are present in the sets that are passed as arguments to the intersection function. The argument must be a set, so we need to convert other collection or seq values to a set first before we use it as an argument for the function.

In the following example we use one, two or three arguments for the intersection function and also convert other types to a set to be used as argument:

(ns mrhaki.sample
  (:require [clojure.set :refer [intersection]]
            [clojure.test :refer [is]]))

;; Use intersection with sets to find common elements.
(is (= #{"Clojure"} (intersection #{"Java" "Scala" "Clojure"} #{"Clojure" "Groovy"})))

;; An empty set is returned if there is no common element.
(is (= #{} (intersection #{"Java" "Groovy" "Clojure"} #{"C++" "C#"})))

;; We can use more than two sets to find intersections.
(is (= #{"Clojure"} (intersection #{"Java" "Scala" "Clojure"} 
                                  #{"Clojure" "Groovy"} 
                                  #{"Groovy" "JRuby" "Clojure"})))

;; With one set intersections returns the set.
(is (= #{"Clojure" "Groovy"} (intersection #{"Clojure" "Groovy"})))

;; Only sets are allowed as arguments for the intersection function.
;; If one of the arguments is not a set the return value is unexpected. 
(is (= #{} (intersection #{"Clojure" "Groovy"} ["Java" "Scala" "Clojure"])))
;; But we can convert a non-set to a set with the set function.
(is (= #{"Clojure"} (intersection #{"Clojure" "Groovy"} (set ["Java" "Scala" "Clojure"]))))
(is (= #{"Clojure"} (intersection #{"Clojure" "Groovy"} (set '("Java" "Scala" "Clojure")))))
;; Or using into #{}.
(is (= #{"Clojure"} (intersection #{"Clojure" "Groovy"} 
                                  (into #{} (vals {:platform "Java" :language "Clojure"})))))

Written with Clojure 1.10.1