Search code examples
arraysswiftfilterstructure

Swift - Find Specific Differences in Arrays of Structs


If I have a structure, say:

struct Subject { 
 var subjectID: String?
 var name: String?
 var note: String?
}

And I have two arrays of this structure: Array1 and Array2.

For example:

Array1 = [(subjectID = "T", name = "H", note = "DF"), (subjectID = "F", name = "H", note = "SD")]
Array2 = [(subjectID = "T", name "G", note = "DF"), (subjectID = "R", name = "F", note = "SDF")]

I want to return a new array, which consists of a subset of elements from Array2 that match the subjectID field of Array1 but have different name and/or note elements.

In the example above, the returned array would be:

[(subjectID = "T", name "G", note = "DF")]

As it contains the same subjectID (in this case T) as in Array1 but the name field is different. Note that the fields for this new returned array should be original values from Array2 (ex: you don't need to correct them to match Array1)

Is there an easy way (ex: one-two lines of code) to do this without brute forcing it?

Thanks!


Solution

  • There are good answers here, I prefer to keep the test simple.

    First the setup

    struct Subject {
        var subjectID: String?
        var name: String?
        var note: String?
    }
    
    let array1 = [Subject(subjectID: "T", name: "H", note: "DF"), Subject(subjectID: "F", name: "H", note: "SD")]
    let array2 = [Subject(subjectID: "T", name: "G", note: "DF"), Subject(subjectID: "R", name: "F", note: "SDF")]
    

    Now lets look at the actual algorithm. array2.filter returns an array of Subjects in the array2 in which the block returns true. array1.contains returns true if any of the Subjects in array1 returns true. The test itself is exactly what you described. Are the subject id equal and does either the name or the note differ.

    let result = array2.filter { s2 in
        array1.contains { s1 in
            s1.subjectID == s2.subjectID && (s1.name != s2.name || s1.note != s2.note)
        }
    }