Test whether a list contains a specific value in Clojure

Viewed 87227

What is the best way to test whether a list contains a given value in Clojure?

In particular, the behaviour of contains? is currently confusing me:

(contains? '(100 101 102) 101) => false

I could obviously write a simple function to traverse the list and test for equality, but there must surely be a standard way to do this?

19 Answers

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. Michał has already explained why.

; 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, 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 are searching for a falsy value (false or nil).

    ; will not work
    (some #{false} [true false true]) ; = nil
    

    In these cases, you should use the built-in predicate function for that value, false? or nil?:

    (some false? [true false true]) ; = true
    
  4. 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
    

Also, see Michał’s answer for ways to check whether any of multiple targets are contained in a sequence.

Another option:

((set '(100 101 102)) 101)

Use java.util.Collection#contains():

(.contains '(100 101 102) 101)

Found this late. But this is what im doing

(some (partial = 102) '(101 102 103)) 
Related