iosarraysswiftarraylist

Swift - Determine if Array1 contains at least one object from Array2


I have 2 Arrays. Say, array1 = [1,2,3,4,5] and array2 = [2,3]. How could I check in swift if array1 contains at least one item from array2?


Solution

  • You can do this by simply passing in your array2's contains function into your array1's contains function (or vice versa), as your elements are Equatable.

    let array1 = [2, 3, 4, 5]
    let array2 = [20, 15, 2, 7]
    
    // this is just shorthand for array1.contains(where: { array2.contains($0) })
    if array1.contains(where: array2.contains) {
        print("Array 1 and array 2 share at least one common element")
    } else {
        print("Array 1 doesn't contains any elements from array 2")
    }
    

    This works by looping through array 1's elements. For each element, it will then loop through array 2 to check if it exists in that array. If it finds that element, it will break and return true – else false.

    This works because there are actually two flavours of contains. One takes a closure in order to check each element against a custom predicate, and the other just compares an element directly. In this example, array1 is using the closure version, and array2 is using the element version. And that is the reason you can pass a contains function into another contains function.


    Although, as correctly pointed out by @AMomchilov, the above algorithm is O(n2). A good set intersection algorithm is O(n), as element lookup is O(1). Therefore if your code is performance critical, you should definitely use sets to do this (if your elements are Hashable), as shown by @simpleBob.

    Although if you want to take advantage of the early exit that contains gives you, you'll want to do something like this:

    extension Sequence where Iterator.Element : Hashable {
    
        func intersects<S : Sequence>(with sequence: S) -> Bool
            where S.Iterator.Element == Iterator.Element
        {
            let sequenceSet = Set(sequence)
            return self.contains(where: sequenceSet.contains)
        }
    }
    

    if array1.intersects(with: array2) {
        print("Array 1 and array 2 share at least one common element")
    } else {
        print("Array 1 doesn't contains any elements from array 2")
    }
    

    This works much the same as the using the array's contains method – with the significant difference of the fact that the arraySet.contains method is now O(1). Therefore the entire method will now run at O(n) (where n is the greater length of the two sequences), with the possibility of exiting early.