ClojureDocs

Nav

Namespaces

difference

clojure.set

Available since 1.0
  • (difference s1)
  • (difference s1 s2)
  • (difference s1 s2 & sets)
Return a set that is the first set without elements of the remaining sets
5 Examples
user=> (difference #{1 2 3})
#{1 2 3}
user=> (difference #{1 2} #{2 3})
#{1}
user=> (difference #{1 2 3} #{1} #{1 4} #{3})
#{2}
user=> (difference (set (keys {:1 1 :2 2 :3 3})) (set (keys {:1 1 :2 2})))
#{:3}
user=> (difference (set (keys {:1 1 :2 2})) (set (keys {:1 1 :2 2 :3 3})))
#{}
user=> (difference #{:a :b :c :d} (difference #{:a :b :c :d} #{:c :e :a :f :d}))
#{:a :c :d}
;; Advice: Do not call difference 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 difference that is identical to Clojure's,
;; except it checks the types of its arguments.

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

;; This looks like what someone might expect.  It _happens_ to give
;; back the same answer as if you coerced the second argument to a
;; set.
user=> (difference #{1 3 5} [1 2 3 4 5 6])
#{}

;; This is not the difference between the two collections (if they
;; were both sets) at all!
user=> (difference #{1 3 5} [2 4 6 8 10 12])
#{}

;; Give it only sets, and it returns the correct answer.
user=> (set/difference #{1 3 5} #{2 4 6 8 10 12})
#{1 3 5}

;; Also not the correct set difference, because the second arg is a
;; vector, not a set.
user=> (difference #{-1 10 20 30} [-1 10 20 30 40])
#{20 -1 30 10}

;; This is correct.
user=> (difference #{-1 10 20 30} #{-1 10 20 30 40})
#{}

;; Why not change the definition of difference so it 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 difference 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
;; difference subtracts the trailing sets
(def s1 #{1 2})
(def s2 #{2 3})
(set/difference s1 s2)
;;=> #{1}

;; to get the exclusive union #{1 3} (or "XOR"):
(set/difference
  (set/union s1 s2)
  (set/intersection s1 s2))
;;=> #{1 3}

;; You can extend this to maps:
(defn- map-xor [m1 m2]
  (map (juxt (fn [[k1 _] _] k1)
             (fn [[_ v1] [_ v2]]
               (set/difference
                 (set/union (set v1) (set v2))
                 (set/intersection (set v1) (set v2)))))
    m1
    m2))
(map-xor 
  {:a [1 2] :b [2 3]}
  {:a [2 3] :b [3]})
;;=> ([:a #{1 3}] 
      [:b #{2}])
See Also

Return a set that is the union of the input sets

Added by mmwaikar

Return a set that is the intersection of the input 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

disj[oin]. Returns a new set of the same (hashed/sorted) type, that does not contain key(s).

Added by reborg
0 Notes
No notes for difference