Skip to content

clojure.core/contains?

View this page on ClojureDocs

Type: function Added: Clojure 1.0 Examples: 3 Runnable: 2
([coll key])

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

by Brian Marick on . May have evaluation errors.
by stand on
by reborg on

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:

  1. Consider whether you really need a vector or list. If you use a set instead, contains? will work.

    (contains? #{:a :b :c} :b) ; = true

  2. Use some instead, wrapping the target in a set, as follows:

    (some #{:b} [:a :b :c]) ; = :b, which is truthy

  3. The set-as-function shortcut will not work if you might be searching for a falsy value (false or nil).

    ; 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

  1. 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

Java API Docs are here

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


Content from the matching ClojureDocs page, with authors credited on each contribution.