Swift-查找结构数组中的特定差异

时间:2018-10-24 19:01:36

标签: arrays swift filter structure

如果我有结构,请说:

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

我有两个具有这种结构的数组:Array1和Array2。

例如:

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")]

我要返回一个新数组,该数组由Array2中与subjectID的{​​{1}}字段匹配但具有不同{ {1}}和/或Array1元素。

在上面的示例中,返回的数组为:

name

因为它包含与note中相同的[(subjectID = "T", name "G", note = "DF")] (在本例中为subjectID),但是T字段不同。请注意,此新返回数组的字段应为Array1中的原始值(例如:您无需更正它们以匹配name

是否有一种简单的方法(例如:一两行代码)来执行此操作而不用强行强制执行它?

谢谢!

4 个答案:

答案 0 :(得分:2)

这里有很好的答案,我宁愿保持测试简单。

首先设置

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")]

现在让我们看一下实际算法。 array2.filter返回Subjectarray2的数组,其中该块返回true。如果array1.contains中的true中的任何Subject返回array1,则true返回let result = array2.filter { s2 in array1.contains { s1 in s1.subjectID == s2.subjectID && (s1.name != s2.name || s1.note != s2.note) } } 。测试本身就是您所描述的。主题ID是否相等,名称或注释是否相同?

<thread>

答案 1 :(得分:0)

您可以这样做:

let subjectsByID = Dictionary(grouping: array1, by: { $0.subjectID })

let diff = array2.filter { subject in
    if let other = subjectsByID[subject.subjectID]?.first {
        return subject.name != other.name || subject.note != other.note
    } else {
        return false
    }
}

它将按ID对第一个数组中的主题进行分组,然后根据是否有该ID的条目使用不同的名称或注释来过滤第二个数组。您没有指定在第一个数组中有多个具有相同ID的条目时要怎么做,因此它只会查看第一个。

答案 2 :(得分:0)

您可以根据第一个数组元素过滤第二个数组元素,例如:

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")]

let result = Array2.filter { subject -> Bool in
    for s in Array1 {
        if subject.subjectID == s.subjectID && subject.name != s.name && subject.note != s.subjectID { return true }
    }

    return false
}

result应包含您的要求。请记住,它具有嵌套迭代(O(n²))的复杂性。

答案 3 :(得分:0)

我结合使用了forEach和filter来查找所需的元素

var result = [Subject]()
arr1.forEach( { subject in
    result.append(contentsOf: arr2.filter( { $0.subjectID == subject.subjectID && 
                                            ($0.name != subject.name || 
                                             $0.note != subject.note) }))
})

要获得更简洁的代码,可以在struct中对函数进行检查

struct Subject {
   ...

    func isModifiedComparedTo(_ subject: Subject) -> Bool {
        return self.subjectID == subject.subjectID && (self.name != subject.name || self.note != subject.note)
    }
}

var result = [Subject]()
arr1.forEach( { subject in
    result.append(contentsOf: arr2.filter({$0.isModifiedComparedTo(subject)}))
})