# How to get list of common elements of 2 array in Swift?

I have two arrays:

``````fruitsArray = ["apple", "mango", "blueberry", "orange"]
vegArray = ["tomato", "potato", "mango", "blueberry"]
``````

How can I get the list of common items in those two array which gives

``````ouptput = ["mango", "blueberry"]
``````

I can't use `if contains(array, string)` as I want to compare 2 arrays.

You can also use `filter` and `contains` in conjunction:

``````let fruitsArray = ["apple", "mango", "blueberry", "orange"]
let vegArray = ["tomato", "potato", "mango", "blueberry"]

// only Swift 1
let output = fruitsArray.filter{ contains(vegArray, \$0) }

// in Swift 2 and above
let output = fruitsArray.filter{ vegArray.contains(\$0) }
// or
let output = fruitsArray.filter(vegArray.contains)
``````

# `Set` vs `Array` for a single computation of common elements

We consider the following code snippet:

``````let array1: Array = ...
let array2: Array = ...

// `Array`
let commonElements = array1.filter(array2.contains)

// vs `Set`
let commonElements = Array(Set(array1).intersection(Set(array2)))
// or (performance wise equivalent)
let commonElements: Array = Set(array1).filter(Set(array2).contains)
``````

I have made some (artificial) benchmarks with `Int` and short/long `String`s (10 to 100 `Character`s) (all randomly generated). I always use `array1.count == array2.count`

I get the following results:

If you have more than `critical #(number of) elements` converting to a `Set` is preferable

``````data         |  critical #elements
-------------|--------------------
Int |        ~50
short String |       ~100
long String |       ~200
``````

### Explanation of the results

Using the `Array` approach uses "Brute force"-search which has time complexity `O(N^2)` where `N = array1.count = array2.count` which is in contrast to the `Set` approach `O(N)`. However the conversion from `Array` to `Set` and back is very expensive for large data which explains the increase of `critical #elements` for bigger data types.

# Conclusion

For small `Array`s with about 100 elements the `Array` approach is fine but for larger ones you should use the `Set` approach.

If you want to use this "common elements"-operation multiple times it is advisable to use `Set`s only if possible (the type of the elements has to be `Hashable`).

### Final Remarks

A conversion from `Array` to `Set` is kind of expensive while the conversion from `Set` to `Array` is in contrast very inexpensive.

Using `filter` with `.filter(array1.contains)` is performance wise faster than `.filter{ array1.contains(\$0) }` since:

• the last one creates a new closure (only once) whereas the first one passes only a function pointer
• for the last one the call of the closure creates an additional stack frame which costs space and time (multiple times: `O(N)`)
• Whenever applicable, @Mousavian's `Set`-based answer is better, but this is good in the rare circumstance when the type is `Equatable` but not `Hashable`. – Alexander Dec 10 '17 at 0:03

Convert them to Set and use intersect() function:

``````let fruitsArray = ["apple", "mango", "blueberry", "orange"]
let vegArray = ["tomato", "potato", "mango", "blueberry"]
let fruitsSet = Set(fruitsArray)
let vegSet = Set(vegArray)
let output = Array(fruitsSet.intersection(vegSet))
``````
• This should really be the accepted answer. BTW you can intersect a `Set` with any collection (without a loss of performance), so you don't need to generate `vegSet` (which is O(n)` in itself) – Alexander Dec 10 '17 at 0:01
• Thank you Alexander. I have Set implementations as an extension on Array, e.g.: extension Array where Element: Hashable { public func isSubset(of other: [Element]) -> Bool { let selfSet = Set(self) return selfSet.isSubset(of: other) } } – Giles Feb 28 '18 at 12:05

You don't need a Set (as the comments above have mentioned).

You could instead use a generic function, similar to the one Apple use in their Swift Tour, and thus avoid casting:

``````func anyCommonElements <T, U where T: SequenceType, U: SequenceType, T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (lhs: T, rhs: U) -> Bool {
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
return true
}
}
}
return false
}
``````

This function can take any two arrays (SequenceTypes) and if any of their elements are the same it returns true.

You could simply modify this generic function to package up an array of strings and return that instead.

For example like this:

``````func arrayOfCommonElements <T, U where T: SequenceType, U: SequenceType, T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (lhs: T, rhs: U) -> [T.Generator.Element] {
var returnArray:[T.Generator.Element] = []
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
returnArray.append(lhsItem)
}
}
}
return returnArray
}
``````

Usage like this:

``````var one = ["test2", "dog", "cat"]
var other = ["test2", "cat", "dog"]

var result = arrayOfCommonElements(one,other)

print(result) //prints [test2, dog, cat]
``````

The added benefit here is that this function also works with all same typed arrays. So later if you need to compare two `[myCustomObject]` arrays, once they both conform to equatable, you're all set! (pun intended)

Edit: (For non common elements) you could do something like this

``````func arrayOfNonCommonElements <T, U where T: SequenceType, U: SequenceType, T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (lhs: T, rhs: U) -> [T.Generator.Element] {

var returnArray:[T.Generator.Element] = []
var found = false

for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
found = true
break
}
}

if (!found){
returnArray.append(lhsItem)
}

found = false
}
for rhsItem in rhs {
for lhsItem in lhs {
if rhsItem == lhsItem {
found = true
break
}
}

if (!found){
returnArray.append(rhsItem)
}

found = false
}
return returnArray
}
``````

This implementation is ugly though.

• Hi, this is working for me... Can you please tell me how to get the non-common elements of the `fruitsArray` ? – AAA Sep 10 '15 at 12:13
• What is the drawback in using Set? – AAA Sep 13 '15 at 9:24
• @AAA there is no drawback to using sets or even other high level functions like filter and contains. However, since you're starting with Arrays I wanted to show you that you didn't have to change their type to find common elements. Furthermore, its always good to understand the fundamentals, Sets will (most likely) in their implementation use something like the above (although it will be more elegant I'm quite sure). – Woodstock Sep 13 '15 at 9:39
• The drawback to using `Set` is that your items must be `Hashable` where basing the solution on `Array` only requires that they be `Equatable` – David Berry Mar 16 '16 at 16:25
• You should offer the Set-based, O(n) solutions as default, and offer these crappy (O(N^2)) array-based solutions only as a backup for the very niche case of equatable but not hashable items. – Alexander Dec 9 '17 at 23:33

The following works with swift 4:

``````   let fruitsArray = ["apple", "mango", "blueberry", "orange"]
let vegArray = ["tomato", "potato", "mango", "blueberry"]

var someHash: [String: Bool] = [:]

fruitsArray.forEach { someHash[\$0] = true }

var commonItems = [String]()

vegArray.forEach { veg in
if someHash[veg] ?? false {
commonItems.append(veg)
}
}

print(commonItems)
``````

A generic method, inspired by The Swift Programming Language (Swift 3) exercise:

``````func commonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> [T.Iterator.Element]
where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element {
var common: [T.Iterator.Element] = []

for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
common.append(lhsItem)
}
}
}
return common
}
``````

Then, use it like this:

``````var a = [3,88,74]
var b = [1,3,88]

print("commons: \(commonElements(a, b))")

--> commons: [3, 88]
``````

Using Set and also intersection as follows:

``````func findIntersection (firstArray : [Int], secondArray : [Int]) -> [Int]
{
return [Int](Set<Int>(firstArray).intersection(secondArray))
}

print (findIntersection(firstArray: [2,3,4,5], secondArray: [1,2,3]))
``````
{"ft_lang_label":"__label__en","ft_lang_prob":0.6599543,"math_prob":0.82661897,"size":2107,"snap":"2021-04-2021-17","text_gpt3_token_len":546,"char_repetition_ratio":0.18354732,"word_repetition_ratio":0.3058104,"special_character_ratio":0.26150927,"punctuation_ratio":0.21105528,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.97953933,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-01-22T01:20:30Z\",\"WARC-Record-ID\":\"<urn:uuid:8d0df144-c3dd-4e9a-aa09-bacc5eb719b9>\",\"Content-Length\":\"223192\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:96064b5d-bfdd-4abf-83f1-72ca7f5a5593>\",\"WARC-Concurrent-To\":\"<urn:uuid:d6b58e2a-7b90-4204-a014-e8df8de35eb2>\",\"WARC-IP-Address\":\"151.101.193.69\",\"WARC-Target-URI\":\"https://stackoverflow.com/questions/32439289/how-to-get-list-of-common-elements-of-2-array-in-swift\",\"WARC-Payload-Digest\":\"sha1:DC26JZSFP7EOVRDJHR2JDK2NFF5ZCM4B\",\"WARC-Block-Digest\":\"sha1:ERWQDKF2QKHC2NM7AVWFFS42VIR6JU3P\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-04/CC-MAIN-2021-04_segments_1610703528672.38_warc_CC-MAIN-20210121225305-20210122015305-00700.warc.gz\"}"}