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
?
-
2Have you tried something? – luk2302 May 18 '16 at 12:17
-
See http://stackoverflow.com/questions/24589181/set-operations-union-intersection-on-swift-array for some ideas what can be done with `Array` and `Set`. – Martin R May 18 '16 at 12:38
6 Answers
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.
-
1
-
-
Could you include a link to some documentation for the contains function? Thanks. – Arc676 May 21 '16 at 12:31
-
1@Arc676 In my third paragraph I have links to both [the closure](https://developer.apple.com/library/ios/documentation/Swift/Reference/Swift_SequenceType_Protocol/index.html#//apple_ref/swift/intfm/SequenceType/s:FEsPs12SequenceType8containsFzFzWx9Generator7Element_SbSb) and [element](https://developer.apple.com/library/ios/documentation/Swift/Reference/Swift_SequenceType_Protocol/index.html#//apple_ref/swift/intfm/SequenceType/s:FesRxs12SequenceTypeWx9Generator7Element_s9EquatablerS_8containsFWxS0_S1__Sb) `contains` functions – I will add a link in the first paragraph though :) – Hamish May 21 '16 at 12:32
-
And how about different of 2 objects list, at least one property contain?. this answer just the same two object list. I's stucking on this. haha – Leang Socheat Feb 23 '18 at 04:41
-
@LeangSocheat Not entirely sure what you mean; it would probably be best if you [asked a new question](https://stackoverflow.com/questions/ask) giving a clear example of what you're trying to achieve. – Hamish Feb 23 '18 at 12:01
With Swift 5, you can use one of the following paths in order to find if two arrays have common elements or not.
#1. Using Set
isDisjoint(with:)
method
Set
has a method called isDisjoint(with:)
. isDisjoint(with:)
has the following declaration:
func isDisjoint(with other: Set<Element>) -> Bool
Returns a Boolean value that indicates whether the set has no members in common with the given sequence.
In order to test if two arrays have no common elements, you can use the Playground sample code below that implements isDisjoint(with:)
:
let array1 = [1, 3, 6, 18, 24]
let array2 = [50, 100, 200]
let hasNoCommonElement = Set(array1).isDisjoint(with: array2)
print(hasNoCommonElement) // prints: true
#2. Using Set
intersection(_:)
method
Set
has a method called intersection(_:)
. intersection(_:)
has the following declaration:
func intersection<S>(_ other: S) -> Set<Element> where Element == S.Element, S : Sequence
Returns a new set with the elements that are common to both this set and the given sequence.
In order to test if two arrays have no common elements or one or more common elements, you can use the Playground sample code below that implements intersection(_:)
:
let array1 = [1, 3, 6, 18, 24]
let array2 = [2, 3, 18]
let intersection = Set(array1).intersection(array2)
print(intersection) // prints: [18, 3]
let hasCommonElement = !intersection.isEmpty
print(hasCommonElement) // prints: true

- 89,880
- 29
- 256
- 218
-
I'd be glad to have the confirmation from someone who really knows about this stuff (not me), but I'd imagine that `isDisjoint(with:)` is more performance efficient than doing `!intersection.isEmpty`? – Clément Cardonnel Jun 22 '20 at 06:34
Swift 5
Just make an extension
public extension Sequence where Element: Equatable {
func contains(anyOf sequence: [Element]) -> Bool {
return self.filter { sequence.contains($0) }.count > 0
}
}
Use:
let someArray = ["one", "two", "three"]
let string = "onE, Cat, dog"
let intersects = string
.lowercased()
.replacingOccurrences(of: " ", with: "")
.components(separatedBy: ",")
.contains(anyOf: someArray)
print(intersects) // true
let a1 = [1, 2, 3]
let a2 = [2, 3, 4]
Option 1
a2.filter { a1.contains($0) }.count > 1
Option 2
a2.reduce(false, combine: { $0 || a1.contains($1) })

- 11,963
- 3
- 41
- 66
Hope this helps.
//
// Array+CommonElements.swift
//
import Foundation
public extension Array where Element: Hashable {
func set() -> Set<Array.Element> {
return Set(self)
}
func isSubset(of array: Array) -> Bool {
self.set().isSubset(of: array.set())
}
func isSuperset(of array: Array) -> Bool {
self.set().isSuperset(of: array.set())
}
func commonElements(between array: Array) -> Array {
let intersection = self.set().intersection(array.set())
return intersection.map({ $0 })
}
func hasCommonElements(with array: Array) -> Bool {
return self.commonElements(between: array).count >= 1 ? true : false
}
}

- 59
- 2