How to Find the Difference Between Two Arrays in Swift
Swift's Set type makes membership-based array difference a one-liner, but Swift also has something most languages here don't: a built-in CollectionDifference for when you need to know exactly where items were inserted or removed, not just which ones changed.
Quick answer
The fast way is Set(a).subtracting(b), converted back to an array: let aOnly = Array(Set(a).subtracting(b)). It's O(n + m) but drops duplicates and order. To keep both, filter a directly against a Set built from b: a.filter { !Set(b).contains($0) }. For a positional diff (insertions and removals with index information), use a.difference(from: b) instead of a Set-based approach.
Need the same thing in another language?
See the full reference for Kotlin, Java, Python, SQL, and more.
Set subtracting(): the standard approach
let a = ["apple", "banana", "cherry", "banana"] let b = ["banana", "date"] let aOnly = Array(Set(a).subtracting(b)) print(aOnly) // ["apple", "cherry"] - order not guaranteed, duplicate "banana" dropped
Set(a).subtracting(b) is O(n + m) and reads clearly, but converting a to a Set loses both its original ordering and any duplicate entries.
Order-preserving filter (keeps duplicates)
let a = ["apple", "banana", "cherry", "banana"]
let b = ["banana", "date"]
let setB = Set(b)
let aOnly = a.filter { !setB.contains($0) }
print(aOnly) // ["apple", "cherry"] - order preserved Here only b is converted to a Set, so a's original order and any duplicates not present in b are kept. Set.contains() is O(1), so the whole filter is still O(n + m).
CollectionDifference: a positional diff
let a = ["apple", "banana", "cherry"]
let b = ["apple", "cherry"]
let diff = a.difference(from: b)
for change in diff {
switch change {
case .insert(let offset, let element, _):
print("inserted \(element) at \(offset)")
case .remove(let offset, let element, _):
print("removed \(element) at \(offset)")
}
}
// inserted banana at 1 difference(from:) is a different kind of diff than everything else on this page - it's positional, describing the minimal sequence of inserts and removes needed to turn b into a, similar to what a text diff tool does with lines. It's the right tool when you need index information (for example, animating a UITableView or List update), not when you only care about set membership.
Symmetric difference
let a: Set = ["apple", "banana", "cherry"] let b: Set = ["banana", "date"] let symDiff = a.symmetricDifference(b) print(symDiff) // ["apple", "cherry", "date"]
symmetricDifference() gives you everything in exactly one of the two sets in a single call, no manual combining of two subtracts required.
Just need the answer, not the code? Paste both lists.
Open Compare 2 Lists →Frequently Asked Questions
What is the standard way to find the difference between two arrays in Swift?
let aOnly = Array(Set(a).subtracting(b)) is the fast, idiomatic approach - convert to Sets and subtract. It's O(n + m) but drops duplicates and doesn't preserve the original order of a.How do I get array difference in Swift without losing order or duplicates?
let setB = Set(b); let aOnly = a.filter { !setB.contains($0) }. This keeps a's original order and any duplicate items that aren't in b, while still using an O(1) Set lookup for each check.Do array elements need to conform to Hashable for these approaches?
What is CollectionDifference and when should I use it instead of Set subtracting?
a.difference(from: b) returns a CollectionDifference describing the exact insertions and removals needed to turn b into a, preserving position information rather than just membership. Use it when you need to know where items changed (for animating a table view diff, for example), not just which items changed - Set-based subtracting() is the right tool when you only care about membership.How do I get the symmetric difference of two arrays in Swift?
Set(a).symmetricDifference(b) returns every element that is in exactly one of the two collections, as a Set. Convert back to an array with Array(...) if you need to preserve the Array type, keeping in mind the result won't retain either array's original order.How do I compare two arrays of custom structs by one property in Swift?
let idsB = Set(b.map { $0.id }); let aOnly = a.filter { !idsB.contains($0.id) }. This avoids needing the whole struct to conform to Hashable if you only care about one field.How do I compare two arrays case-insensitively in Swift?
let setB = Set(b.map { $0.lowercased() }); let aOnly = a.filter { !setB.contains($0.lowercased()) }. The original casing of items in a is preserved in the output since you're only lowercasing for the comparison.