I have two arrays like this:
var arrayA = [\"Mike\", \"James\", \"Stacey\", \"Steve\"]
var arrayB = [\"Steve\", \"Gemma\", \"James\", \"Lucy\"]
Using the Array → Set → Array
method mentioned by Antonio, and with the convenience of an operator, as freytag pointed out, I've been very satisfied using this:
// Swift 3.x/4.x
func - <Element: Hashable>(lhs: [Element], rhs: [Element]) -> [Element]
{
return Array(Set<Element>(lhs).subtracting(Set<Element>(rhs)))
}
For smaller arrays I use:
/* poormans sub for Arrays */
extension Array where Element: Equatable {
static func -=(lhs: inout Array, rhs: Array) {
rhs.forEach {
if let indexOfhit = lhs.firstIndex(of: $0) {
lhs.remove(at: indexOfhit)
}
}
}
static func -(lhs: Array, rhs: Array) -> Array {
return lhs.filter { return !rhs.contains($0) }
}
}
@francesco-vadicamo's answer in Swift 2/3/4+
arrayA = arrayA.filter { !arrayB.contains($0) }
Original answer
This can also be implemented as a minus func:
func -<T:RangeReplaceableCollectionType where T.Generator.Element:Equatable>( lhs:T, rhs:T ) -> T {
var lhs = lhs
for element in rhs {
if let index = lhs.indexOf(element) { lhs.removeAtIndex(index) }
}
return lhs
}
Now you can use
arrayA - arrayB
Updated implementation for Swift 5
func -<T: RangeReplaceableCollection>(lhs: T, rhs: T) -> T where T.Iterator.Element: Equatable {
var lhs = lhs
for element in rhs {
if let index = lhs.firstIndex(of: element) { lhs.remove(at: index) }
}
return lhs
}
I agree with Antonio's answer, however for small array subtractions you can also use a filter closure like this:
let res = arrayA.filter { !contains(arrayB, $0) }
matt and freytag's solutions are the ONLY ones that account for duplicates and should be receiving more +1s than the other answers.
Here is an updated version of matt's answer for Swift 3.0:
var arrayA = ["Mike", "James", "Stacey", "Steve"]
var arrayB = ["Steve", "Gemma", "James", "Lucy"]
for word in arrayB {
if let ix = arrayA.index(of: word) {
arrayA.remove(at: ix)
}
}