Fast Array / NSArray lookup for multiple values
Two big questions:
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 a way to search an array for more than one value? i.e. Can I write below to search an array for multiple values and return true if any of the values are found? The second part of the question is how can I do this for NSArray?
var array = [1,2,3,4,5]
contains(array, (0,2,3)) // this doesn't work of course but you get the point
source to share
One option is to use Set
for search queries:
var array = [1,2,3,4,5]
let searchTerms: Set = [0,2,3]
!searchTerms.isDisjointWith(array)
(You must discard the value isDisjointWith
, as it returns false
when at least one of the conditions is found.)
Note that you can also expand Array
to add a shortcut for this:
extension Array where Element: Hashable {
func containsAny(searchTerms: Set<Element>) -> Bool {
return !searchTerms.isDisjointWith(self)
}
}
array.containsAny([0,2,3])
As for NSArray
, you can use a version contains
that takes a block to match:
var array2: NSArray = [1,2,3,4,5]
array2.contains { searchTerms.contains(($0 as! NSNumber).integerValue) }
Explanation of the closure syntax (as requested in the comments): you can put a closure outside of a ()
method call if it is the last parameter, and if it is the only parameter, you can omit it entirely ()
. $0
is the default name of the first closing argument ( $1
will be the second, etc.). And return
can be omitted if the closure is only one expression. Long equivalent:
array2.contains({ (num) in
return searchTerms.contains((num as! NSNumber).integerValue)
})
source to share
You can chain together with the 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)
source to share