clojure.core/contains?¶
Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'.
Examples¶
Note by robertpostill¶
If like me you wanted to find a value in a collection and read this article then you'll need to find an alternative. So instead of:
(contains (1 2 3) 1)
I used:
(some #(= 1 %) (1 2 3))
Hope that helps.
Note by devijvers¶
For collections I use the java.util.Collection#contains() method:
user=> (.contains [1 2 3] 1) true user=> (.contains [1 2 3] 4) false
Note by uvtc¶
As Rich points out on the ML:
contains? tells you whether or not get will succeed. It is not a "rummager".
contains? and get abstract over fast lookup.
Note by roryokane¶
If you have a vector or list and want to check whether a value is contained in it, you will find that contains? does not work.
; does not work as you might expect (contains? [:a :b :c] :b) ; = false
There are four things you can try in this case:
-
Consider whether you really need a vector or list. If you use a set instead,
contains?will work.
(contains? #{:a :b :c} :b) ; = true -
Use
someinstead, wrapping the target in a set, as follows:
(some #{:b} [:a :b :c]) ; = :b, which is truthy -
The set-as-function shortcut will not work if you might be searching for a falsy value (
falseornil).
; will not work (some #{false} [true false true]) ; = nil
In that case, you will have to write the predicate function the long way:
(some #(= false %) [true false true]) ; = true
- If you will need to do this kind of search a lot, write a function for it:
(defn seq-contains? [coll target] (some #(= target %) coll)) (seq-contains? [true false true] false) ; = true
Note by cloojure¶
In order to determine if an element is contained in the collection, it may be easiest to use the Vector.indexOf() function from java:
(.indexOf (range 10) 5)
;=> 5
(.indexOf [:a :b :c] :b)
;=> 1
Note by tengstrand¶
You may wonder why this statement evaluates to true:
(contains? [1 1 1 1 1] 4)
;=> true
Let's do some investigation to find the answer. First we start by finding out the type of [1 1 1 1 1]:
(class [1 1 1 1 1])
;=> clojure.lang.PersistentVector
So when the statement (contains? [1 1 1 1 1] 4) is evaluated, the function contains? in core.clj is called.
This function delegates to the static Java function contains(Object coll, Object key) in clojure.lang.RT, which discovers that the incoming vector is an instance of Associative (PersistentVector > APersistentVector > IPersistentVector > Associative) and exits with:
return ((Associative) coll).containsKey(key)
This means that these two statements are equivalent, based on the current implementation of PersistentVector:
(contains? [1 1 1 1 1] 4) ; true
(.containsKey [1 1 1 1 1 1] 4) ; true
The method containsKey of APersistentVector is finally called. It checks if the vector has at least four elements (size >= 4) which it has (5) and that's why it returns true. Mystery solved!
Note by coutego¶
This in? function could be a convenient one line replacement for contains? implementing the expected semantics for containers:
(defn in? [xs el] (some #(= % el) xs))
See also¶
- clojure.core/some (15)
- clojure.core/get (8)
Content from the matching ClojureDocs page, with authors credited on each contribution.