Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift search Array/NSArray for multiple values

Two faceted question:

var array = [1,2,3,4,5]
contains(array, 0) // false

var array2: NSArray = [1,2,3,4,5]
array2.containsObject(4) // true

Is there any way to search an Array for more than 1 value? ie. Can I write below to search the array for multiple values and return true if any of the values are found? Second part to the question is how can I do that for an NSArray as well?

var array = [1,2,3,4,5]
contains(array, (0,2,3)) // this doesn't work of course but you get the point
like image 336
Chris Avatar asked Jul 26 '15 05:07

Chris


2 Answers

You can chain contains together with a second array:

// Swift 1.x
contains(array) { contains([0, 2, 3], $0) }

// Swift 2 (as method)
array.contains{ [0, 2, 3].contains($0) }

// and since Xcode 7 beta 2 you can pass the contains function which is associated to the array ([0, 2, 3])
array.contains([0, 2, 3].contains)

// Xcode 12
array.contains(where: [0, 2, 3].contains)
like image 147
Qbyte Avatar answered Oct 01 '22 02:10

Qbyte


One option would be to use a Set for the search terms:

var array = [1,2,3,4,5]
let searchTerms: Set = [0,2,3]
!searchTerms.isDisjointWith(array)

(You have to negate the value of isDisjointWith, as it returns false when at least one of the terms is found.)

Note that you could also extend Array to add a shorthand for this:

extension Array where Element: Hashable {
    func containsAny(searchTerms: Set<Element>) -> Bool {
        return !searchTerms.isDisjointWith(self)
    }
}
array.containsAny([0,2,3])

As for the NSArray, you can use the version of contains which takes a block to determine the match:

var array2: NSArray = [1,2,3,4,5]
array2.contains { searchTerms.contains(($0 as! NSNumber).integerValue) }

Explanation of closure syntax (as requested in comments): you can put the closure outside the () of method call if it's the last parameter, and if it's the only parameter you can omit the () altogether. $0 is the default name of the first argument to the closure ($1 would be the second, etc). And return may be omitted if the closure is only one expression. The long equivalent:

array2.contains({ (num) in
    return searchTerms.contains((num as! NSNumber).integerValue)
})
like image 23
Arkku Avatar answered Oct 01 '22 02:10

Arkku