1

I have two arrays of objects with different sizes. First one with old data, second one with updated data from server (included old data with new), data can be mixed. I want to get difference between these arrays.

My class

class Station {
  var dateOfIssue: Date
  var region: String
  var locality: String
  var bsName: String
  var freqIn: String
  var freqOut: String
  var networkType: String
  var provider: String
  var bsUsableName: String
  ...
}

Arrays I want to compare (example)

var a = [Station]()
var b = [Station]()
for _ in 0...5 {      
  a.append(Station(someRandomStationValue...)
}
b = a
for _ in 0...7{
  b.append(Station(someRandomStationValue...)  //array "b" will contain all that array "a" contains and some new values
}

How to compare these arrays comparing all fields between and get a new array with differences (like in java: b.removeAll(a))?

5
  • Firstly, you need to use var instead of let for initialising your arrays in order to append to it. Secondly, one easy way to get the difference between 2 collections is to use Set. There is a subtract function for that. You can read more here: developer.apple.com/documentation/swift/set/1779475-subtract Commented Apr 30, 2019 at 1:16
  • Oh, about let, it's not a "real" code, wrote it for example, mechanical mistake. About Set thanks, will try Commented Apr 30, 2019 at 1:18
  • tried use Set, it says me "Cannot convert value of type '[Station]' to specified type 'Set'" Commented Apr 30, 2019 at 1:24
  • maybe you can use Set. Commented Apr 30, 2019 at 2:00
  • Do you have any unique property in Station class? Commented Apr 30, 2019 at 2:40

3 Answers 3

1

You can make use of Set which provides in-built .subtract() and .subtracting() methods which removes the common entries inside both the Sets

struct Station: Hashable,CustomStringConvertible {
    var id: Int
    var region: String
    var locality: String
    var bsName: String

    // Just to provide a pretty print statement
    var description: String {
        return "ID: \(id) | region: \(region) | locality: \(locality) | bsName: \(bsName)"
    }
}

var stations1 = Set<Station>()
var stations2 = Set<Station>()

for currentNumber in 0...3 {
    stations1.insert(Station(id: currentNumber, region: "abc", locality: "abc", bsName: "abc"))
}

for currentNumber in 0...5 {
    stations2.insert(Station(id: currentNumber, region: "abc", locality: "abc", bsName: "abc"))
}

// Caluculating the difference here
print(stations2.subtracting(stations1))
Sign up to request clarification or add additional context in comments.

4 Comments

Using a Set loses the original order
Yeah, but if all you want to know is what changes there are between the two, how does the order matter? Plus there is no need for writing your custom logic for eliminating the similar items from the two
Plus the model has a dateOfIssue with which you can later sort the final output
How does your answer differ from @paivaalan's answer?
0

As pointed out by @koropok, a good solution is using Set. The first step is to conform your type to Hashable. For classes, you'd have to implement == and hash(into:) functions, but if you use struct you don't have to do anything else other than declaring the conformance. So:

struct Station: Hashable {
  var dateOfIssue: Date
  var region: String
  ...
}

Now you should be able to add Station into a Set. Thus:

var a = Set<Station>()
for _ in 0...5 {
  a.insert(Station(...))
}
var b = Set<Station>()
a.forEach { b.insert($0) }
for _ in 0...7 {
  b.insert(Station(...))
}

let c = b.subtracting(a)

Set also provides a handy initializer that you can use to turn your Station array into a set:

let s = Set(arrayLiteral: [your, station, objects])

Comments

0

As mentioned in comments by koropok you may use subtract method:

// Added to make original code functional 
// Station must conform to Hashable protocol in order to be stored in the Set
struct Station: Hashable {
    let id: Int
}

var a = [Station]()
for i in 0...5 {
    a.append(Station(id:i))
}

var b = [Station]()
for i in 0...7{
    //array "b" will contain all that array "a" contains and some new values
    b.append(Station(id:i))  
}

var c = Set(b)

// c will contain 6 and 7
c.subtract(a)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.