Home > Net >  How to subtract one array by another array in Swift?
How to subtract one array by another array in Swift?

Time:06-23

I want to subtract array1 by array2 Example:

var array1 = ["the", "people", "prefer", "to", "go", "to", "the","sun","beach"]

var array2 = ["the", "people", "prefer", "go", "to", "the", "moon","beach"]

I want Output:

 ["to","sun"]

What I am trying so far:

let reuslt = array1.filter { ! array2.contains($0) }

Output:

 ["sun"]

it's checking to contain a matching item removing all items if it matches but I want to remove one for one.

CodePudding user response:

Just do it on the computer the way you would do it in your brain. Loop through array2 (not array1). For each element of array2, if that element has a firstIndex in array1, remove the element at that index from array1.

for word in array2 {
    if let index = array1.firstIndex(of: word) {
        array1.remove(at: index)
    }
}

CodePudding user response:

What you effectively want to do is this for loop

for item2 in array2 {
    for i in 0..<array1.count {
        if item2 == array1[i] {
            array1.remove(at: i)
            break
        }
    }
}

Filter works in exactly this way except it doesn't break on the first item but continues to remove all items.

You can also put this into a one liner like this with map instead of filter: array2.map({guard let i = array1.firstIndex(of: $0) else {return}; array1.remove(at: i)})

CodePudding user response:

Your example seems a little confusing / incomplete on the output. But sounds like you could do something like this:

extension Array where Element: Hashable {
    func difference(from other: [Element]) -> [Element] {
        let thisSet = Set(self)
        let otherSet = Set(other)
        return Array(thisSet.symmetricDifference(otherSet))
    }
}

let names1 = ["the", "people", "prefer", "to", "go", "to", "the","sun","beach"]
let names2 = ["the", "people", "prefer", "go", "to", "the", "moon","beach"]
let difference = names1.difference(from: names2)

print(Array(difference)) // ["sun", "moon"]

Using an extension will of course make this code available to all of your arrays in your project. Since we convert the arrays into Sets, duplicates are removed, which may be a issue in your use case.

This Array extension was taken form: https://www.hackingwithswift.com/example-code/language/how-to-find-the-difference-between-two-arrays A vital resoruce for all things swift, especially SwiftUI.

CodePudding user response:

Like above answers, it is ok for a loop contains findIndex and remove from array.

But in other world, I think if the array is too large, the complexity of firstIndex(of:) and remove(at:) cause time and CPU too much for this task - Heat of device can raise a lots too. You can minimize it by using dictionary.

This is an another approach:

func findTheDiff(_ compareArr: [String], _ desArr: [String]) -> [String] {
    var resultArr : [String] = []
    
    var dict : [String: Int] = [:]
    
    for word in compareArr {
        if dict[word] == nil {
            dict[word] = 1
        } else {
            dict[word] = dict[word]!   1
        }
    }
    
    for checkWord in desArr {
        if dict[checkWord] != nil && dict[checkWord]! > 0 {
            dict[checkWord] = dict[checkWord]! - 1
            continue
        }
        
        resultArr.append(checkWord)
    }
    
    return resultArr
}

Usage:

var array1 = ["the", "people", "prefer", "to", "go", "to", "the","sun","beach"]

var array2 = ["the", "people", "prefer", "go", "to", "the", "moon","beach"]
        
var result = self.findTheDiff(array2, array1)
print(result) // ["to", "sun"]

You can find the complexity of firstIndex, remove(at:) below: https://developer.apple.com/documentation/swift/array/firstindex(of:) https://developer.apple.com/documentation/swift/array/remove(at:)-1p2pj

  • Related