Reputation: 567
(def mine '(a b c))
(def yours '(a b))
(remove yours mine)
; should return (c)
I was advised to use remove in another thread but it doesn't work. Anyone can advise?
Upvotes: 0
Views: 644
Reputation: 9865
contains?
is a horrible misnamer in Clojure in my view. (No, it does NOT check, whether an element is contained in a collection! It just checks whether for a key (an index or key) there exist a value in the collection.)
Use some
in combination with #{}
to check for membership in a collection!
(remove #(some #{%} yours) mine)
;; => (c)
Or:
(defn in? [coll x] (some #{x} coll))
(remove #(in? yours %) mine) ;; => {c}
Upvotes: 0
Reputation: 4901
Assuming you want to remove from mine
every element that also exists in yours
, there are a few approaches. You can convert the lists to sets and use difference, like this:
(require '[clojure.set :refer [difference]])
(def mine '(a b c))
(def yours '(a b))
(difference (set mine) (set yours))
;; => #{c}
But this does not preserve the order of elements that remain from mine
. If you want to preserve the order, you can instead use remove. To do that, we first define a yours?
predicate that will return true for an element iff that element occurs in yours
:
(def yours-set (set yours))
(def yours? (partial contains? yours-set))
If our set yours
only contains truthy values like that are neither nil
nor false
, we could define it like (def yours? (set yours))
since a set implements the IFn interface but this approach will not work if yours
contains elements such as nil
or false
as @amalloy pointed out.
(remove yours? mine)
;; => (c)
The above code means that we remove every element from mine
for which yours?
evaluates to true. Yet another, more verbose approach, is to use the opposite of remove, that is filter, and passing in the opposite of the predicate.
(filter (complement yours?) mine)
;; => (c)
but I see no gain of that more verbose approach here.
If you know that you want a vector as a result, you can instead use into, passing in a remove
ing transducer as argument.
(into [] (remove yours?) mine)
;; => [c]
Upvotes: 5