517
votes

In Swift, how can I check if an element exists in an array? Xcode does not have any suggestions for contain, include, or has, and a quick search through the book turned up nothing. Any idea how to check for this? I know that there is a method find that returns the index number, but is there a method that returns a boolean like ruby's #include??

Example of what I need:

var elements = [1,2,3,4,5]
if elements.contains(5) {
  //do something
}
17
if find(elements, 5) != nil { } is not good enough?Martin R
I was hoping for something even cleaner, but its not looking good. I haven't found anything in the documentation or the book yet.jaredsmith

17 Answers

941
votes

Swift 2, 3, 4, 5:

let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
    print("yes")
}

contains() is a protocol extension method of SequenceType (for sequences of Equatable elements) and not a global method as in earlier releases.

Remarks:

Swift older versions:

let elements = [1,2,3,4,5]
if contains(elements, 5) {
    println("yes")
}
139
votes

For those who came here looking for a find and remove an object from an array:

Swift 1

if let index = find(itemList, item) {
    itemList.removeAtIndex(index)
}

Swift 2

if let index = itemList.indexOf(item) {
    itemList.removeAtIndex(index)
}

Swift 3, 4

if let index = itemList.index(of: item) {
    itemList.remove(at: index)
}

Swift 5.2

if let index = itemList.firstIndex(of: item) {
    itemList.remove(at: index)
}
63
votes

Use this extension:

extension Array {
    func contains<T where T : Equatable>(obj: T) -> Bool {
        return self.filter({$0 as? T == obj}).count > 0
    }
}

Use as:

array.contains(1)

Updated for Swift 2/3

Note that as of Swift 3 (or even 2), the extension is no longer necessary as the global contains function has been made into a pair of extension method on Array, which allow you to do either of:

let a = [ 1, 2, 3, 4 ]

a.contains(2)           // => true, only usable if Element : Equatable

a.contains { $0 < 1 }   // => false
43
votes

If you are checking if an instance of a custom class or struct is contained in an array, you'll need to implement the Equatable protocol before you can use .contains(myObject).

For example:

struct Cup: Equatable {
    let filled:Bool
}

static func ==(lhs:Cup, rhs:Cup) -> Bool { // Implement Equatable
    return lhs.filled == rhs.filled
}

then you can do:

cupArray.contains(myCup)

Tip: The == override should be at the global level, not within your class/struct

32
votes

I used filter.

let results = elements.filter { el in el == 5 }
if results.count > 0 {
    // any matching items are in results
} else {
    // not found
}

If you want, you can compress that to

if elements.filter({ el in el == 5 }).count > 0 {
}

Hope that helps.


Update for Swift 2

Hurray for default implementations!

if elements.contains(5) {
    // any matching items are in results
} else {
    // not found
}
21
votes

(Swift 3)

Check if an element exists in an array (fulfilling some criteria), and if so, proceed working with the first such element

If the intent is:

  1. To check whether an element exist in an array (/fulfils some boolean criteria, not necessarily equality testing),
  2. And if so, proceed and work with the first such element,

Then an alternative to contains(_:) as blueprinted Sequence is to first(where:) of Sequence:

let elements = [1, 2, 3, 4, 5]

if let firstSuchElement = elements.first(where: { $0 == 4 }) {
    print(firstSuchElement) // 4
    // ...
}

In this contrived example, its usage might seem silly, but it's very useful if querying arrays of non-fundamental element types for existence of any elements fulfilling some condition. E.g.

struct Person {
    let age: Int
    let name: String
    init(_ age: Int, _ name: String) {
        self.age = age
        self.name = name
    }
}

let persons = [Person(17, "Fred"),   Person(16, "Susan"),
               Person(19, "Hannah"), Person(18, "Sarah"),
               Person(23, "Sam"),    Person(18, "Jane")]

if let eligableDriver = persons.first(where: { $0.age >= 18 }) {
    print("\(eligableDriver.name) can possibly drive the rental car in Sweden.")
    // ...
} // Hannah can possibly drive the rental car in Sweden.

let daniel = Person(18, "Daniel")
if let sameAgeAsDaniel = persons.first(where: { $0.age == daniel.age }) {
    print("\(sameAgeAsDaniel.name) is the same age as \(daniel.name).")
    // ...
} // Sarah is the same age as Daniel.

Any chained operations using .filter { ... some condition }.first can favourably be replaced with first(where:). The latter shows intent better, and have performance advantages over possible non-lazy appliances of .filter, as these will pass the full array prior to extracting the (possible) first element passing the filter.


Check if an element exists in an array (fulfilling some criteria), and if so, remove the first such element

A comment below queries:

How can I remove the firstSuchElement from the array?

A similar use case to the one above is to remove the first element that fulfils a given predicate. To do so, the index(where:) method of Collection (which is readily available to array collection) may be used to find the index of the first element fulfilling the predicate, whereafter the index can be used with the remove(at:) method of Array to (possible; given that it exists) remove that element.

var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]

if let indexOfFirstSuchElement = elements.index(where: { $0 == "c" }) {
    elements.remove(at: indexOfFirstSuchElement)
    print(elements) // ["a", "b", "d", "e", "a", "b", "c"]
}

Or, if you'd like to remove the element from the array and work with, apply Optional:s map(_:) method to conditionally (for .some(...) return from index(where:)) use the result from index(where:) to remove and capture the removed element from the array (within an optional binding clause).

var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]

if let firstSuchElement = elements.index(where: { $0 == "c" })
    .map({ elements.remove(at: $0) }) {

    // if we enter here, the first such element have now been
    // remove from the array
    print(elements) // ["a", "b", "d", "e", "a", "b", "c"]

    // and we may work with it
    print(firstSuchElement) // c
}

Note that in the contrived example above the array members are simple value types (String instances), so using a predicate to find a given member is somewhat over-kill, as we might simply test for equality using the simpler index(of:) method as shown in @DogCoffee's answer. If applying the find-and-remove approach above to the Person example, however, using index(where:) with a predicate is appropriate (since we no longer test for equality but for fulfilling a supplied predicate).

15
votes

The simplest way to accomplish this is to use filter on the array.

let result = elements.filter { $0==5 }

result will have the found element if it exists and will be empty if the element does not exist. So simply checking if result is empty will tell you whether the element exists in the array. I would use the following:

if result.isEmpty {
    // element does not exist in array
} else {
    // element exists
}
8
votes

Swift 4/5

Another way to achieve this is with the filter function

var elements = [1,2,3,4,5]
if let object = elements.filter({ $0 == 5 }).first {
    print("found")
} else {
    print("not found")
}
8
votes

An array that contains a property that equals to

yourArray.contains(where: {$0.propertyToCheck == value })

Returns boolean.

6
votes

As of Swift 2.1 NSArrays have containsObjectthat can be used like so:

if myArray.containsObject(objectImCheckingFor){
    //myArray has the objectImCheckingFor
}
5
votes

Array

let elements = [1, 2, 3, 4, 5, 5]

Check elements presence

elements.contains(5) // true

Get elements index

elements.firstIndex(of: 5) // 4
elements.firstIndex(of: 10) // nil

Get element count

let results = elements.filter { element in element == 5 }
results.count // 2
4
votes

Just in case anybody is trying to find if an indexPath is among the selected ones (like in a UICollectionView or UITableView cellForItemAtIndexPath functions):

    var isSelectedItem = false
    if let selectedIndexPaths = collectionView.indexPathsForSelectedItems() as? [NSIndexPath]{
        if contains(selectedIndexPaths, indexPath) {
            isSelectedItem = true
        }
    }
3
votes

Here is my little extension I just wrote to check if my delegate array contains a delegate object or not (Swift 2). :) It Also works with value types like a charm.

extension Array
{
    func containsObject(object: Any) -> Bool
    {
        if let anObject: AnyObject = object as? AnyObject
        {
            for obj in self
            {
                if let anObj: AnyObject = obj as? AnyObject
                {
                    if anObj === anObject { return true }
                }
            }
        }
        return false
    }
}

If you have an idea how to optimize this code, than just let me know.

2
votes

if user find particular array elements then use below code same as integer value.

var arrelemnts = ["sachin", "test", "test1", "test3"]

 if arrelemnts.contains("test"){
    print("found")   }else{
    print("not found")   }
2
votes

Swift

If you are not using object then you can user this code for contains.

let elements = [ 10, 20, 30, 40, 50]

if elements.contains(50) {

   print("true")

}

If you are using NSObject Class in swift. This variables is according to my requirement. you can modify for your requirement.

var cliectScreenList = [ATModelLeadInfo]()
var cliectScreenSelectedObject: ATModelLeadInfo!

This is for a same data type.

{ $0.user_id == cliectScreenSelectedObject.user_id }

If you want to AnyObject type.

{ "\($0.user_id)" == "\(cliectScreenSelectedObject.user_id)" }

Full condition

if cliectScreenSelected.contains( { $0.user_id == cliectScreenSelectedObject.user_id } ) == false {

    cliectScreenSelected.append(cliectScreenSelectedObject)

    print("Object Added")

} else {

    print("Object already exists")

 }
1
votes

what about using a hash table for the job, like this?

first, creating a "hash map" generic function, extending the Sequence protocol.

extension Sequence where Element: Hashable {

    func hashMap() -> [Element: Int] {
        var dict: [Element: Int] = [:]
        for (i, value) in self.enumerated() {
            dict[value] = i
        }
        return dict
    }
}

This extension will work as long as the items in the array conform to Hashable, like integers or strings, here is the usage...

let numbers = Array(0...50) 
let hashMappedNumbers = numbers.hashMap()

let numToDetect = 35

let indexOfnumToDetect = hashMappedNumbers[numToDetect] // returns the index of the item and if all the elements in the array are different, it will work to get the index of the object!

print(indexOfnumToDetect) // prints 35

But for now, let's just focus in check if the element is in the array.

let numExists = indexOfnumToDetect != nil // if the key does not exist 
means the number is not contained in the collection.

print(numExists) // prints true
0
votes

Swift 4.2 +
You can easily verify your instance is an array or not by the following function.

func verifyIsObjectOfAnArray<T>(_ object: T) -> Bool {
   if let _ = object as? [T] {
      return true
   }

   return false
}

Even you can access it as follows. You will receive nil if the object wouldn't be an array.

func verifyIsObjectOfAnArray<T>(_ object: T) -> [T]? {
   if let array = object as? [T] {
      return array
   }

   return nil
}