我有两个Lecture
的实例,即oldLecture
和newLecture
。Lecture
的简化声明如下(完整版本有更多字段):
struct Lecture: Codable {
let title: String
let class_times: [ClassTime]
let color: [String: String]
}
struct ClassTime: Codable {
let start: Double
let len: Double
}
现在我需要递归地比较oldLecture
和newLecture
,并创建一个新的类似字典的对象,该对象只包含在newLecture
中修改的属性。结果对象将作为PUT
请求发送到服务器。
例如,
var oldLecture = Lecture(title: "lecture1",
class_times: [ClassTime(start: 1, len: 2)],
color: ["fg": "#fff", "bg": "#000"])
var newLecture = Lecture(title: "lecture1",
class_times: [ClassTime(start: 2, len: 3)],
color: ["fg": "#fff", "bg": "#000"])
// the result object should only contain `class_times` key with the value of `[ClassTime(start: 2, len: 3)]`
我已经尝试过了
guard let oldDict = oldLecture.asDictionary() else { return nil }
guard let newDict = newLecture.asDictionary() else { return nil }
var dict: [String: Any] = [:]
for (key, newVal) in newDict {
if let oldVal = oldDict[key], oldVal != newVal {
dict[key] = newVal
}
}
上面的方法不起作用,因为它没有递归地比较oldVal
和newVal
。
有没有更干净的方法来实现这一点,而不使用第三方库,如SwiftyJSON
?
我想,你应该研究一下集合和集合算术。
这段代码可能不完全是您想要的,但它应该为您指明正确的方向。
通过创建两个讲座的时间的对称不同集合,我们得到一个讲座中出现的时间列表,但不是两个讲座。
struct Lecture: Codable, Equatable {
let title: String
let times: [LectureTime]
let color: [String: String]
}
struct LectureTime: Codable, Hashable {
let start: Double
let len: Double
}
var oldLecture = Lecture(title: "lecture1",
times: [.init(start: 1, len: 2), .init(start: 5, len: 2)],
color: ["fg": "#fff", "bg": "#000"])
var newLecture = Lecture(title: "lecture1",
times: [.init(start: 2, len: 3), .init(start: 5, len: 2)],
color: ["fg": "#fff", "bg": "#000"])
if oldLecture != newLecture {
let oldTimes = Set(oldLecture.times)
let newTimes = Set(newLecture.times)
let x = oldTimes.symmetricDifference(newTimes)
print(String(describing:x))
}
打印
[LectureTime(start: 1.0, len: 2.0), LectureTime(start: 2.0, len: 3.0)]
可能你想要扩展你的时间模型,使其可识别——这样你就可以识别出时间被改变了。
获取newLecture和oldLecture之间的所有差异(反之亦然),并将其发送到服务器,尝试这种方法,将Equatable
用于ClassTime
,这将比较ClassTime
对象的内容。getDiff(...)
的结果给出了Lecture
,title
字段的标题不同,color
和class_times
字段的标题也不同。
let result = getDiff(old: oldLecture, new: newLecture)
print("n---> result: (result)")
do {
let data = try JSONEncoder().encode(result)
print("---> data: (data)")
// --> send data to your server
if let str = String(data: data, encoding: .utf8) {
print("---> this is the json object you are sending: (str)")
}
} catch {
print("---> error: (error)")
}
where:
func getDiff(old: Lecture, new: Lecture) -> Lecture {
let title = old.title == new.title ? "" : new.title
let color: [String: String] = new.color.filter{ dic in
!old.color.contains(where: { $0.key == dic.key && $0.value == dic.value })
}
let cls = new.class_times.filter{ !old.class_times.contains($0)}
return Lecture(title: title, class_times: cls, color: color)
}
:
struct ClassTime: Codable, Equatable { // <-- here
let start: Double
let len: Double
}