英文:
How to compare two unequal dictionaries and then add them to a new dictionary in Swift?
问题
我找到了一个类似的问题,但它不能适用于我的问题。
我有两个不相等的字典,想将它们合并成一个,我想用示例来描述:
struct FirstModel: Codable {
var id: Int?
var date: String?
var name: String?
}
struct SecondModel: Codable {
var id: Int?
var date: String?
var age: String?
var position: String?
}
struct FinalModel: Codable {
var first: [FirstModel]?
var second: SecondModel?
}
// dict1: [date: [FirstModel]]
var dict1 = [
"2023-02-19": [FirstModel(id: 10, date: "2023-02-19", name: "Harry"), FirstModel(id: 11, date: "2023-02-19", name: "John")],
"2023-02-13": [FirstModel(id: 12, date: "2023-02-13", name: "Harry"), FirstModel(id: 11, date: "2023-02-13", name: "John")],
"2023-02-12": [FirstModel(id: 13, date: "2023-02-12", name: "Harry"), FirstModel(id: 11, date: "2023-02-12", name: "John")],
"2023-02-10": [FirstModel(id: 14, date: "2023-02-10", name: "Harry"), FirstModel(id: 11, date: "2023-02-10", name: "John")],
]
// dict1: [date: [SecondModel]]
var dict2 = [
"2023-02-19": [SecondModel(id: 10, date: "2023-02-19", age: 12, position: "A"), SecondModel(id: 15, date: "2023-02-19", age: 12, position: "A")],
"2023-02-09": [SecondModel(id: 20, date: "2023-02-09", age: 12, position: "A"), SecondModel(id: 17, date: "2023-02-09", age: 12, position: "A")],
"2023-02-10": [SecondModel(id: 14, date: "2023-02-10", age: 12, position: "A"), SecondModel(id: 16, date: "2023-02-10", age: 12, position: "A")],
"2023-02-12": [SecondModel(id: 27, date: "2023-02-12", age: 12, position: "A"), SecondModel(id: 11, date: "2023-02-12", age: 12, position: "A")],
"2023-02-08": [SecondModel(id: 22, date: "2023-02-08", age: 12, position: "A"), SecondModel(id: 11, date: "2023-02-08", age: 12, position: "A")]
]
我想要一个新的字典,如下所示:
// newDict: [date: [id: [FinalModel]]]
var newDict = [
"2023-02-08": [
11: [FinalModel(first: nil, second: SecondModel(id: 11, date: "2023-02-08", age: 12, position: "A"))],
22: [FinalModel(first: nil, second: SecondModel(id: 22, date: "2023-02-08", age: 12, position: "A"))]
],
"2023-02-09": [
17: [FinalModel(first: nil, second: SecondModel(id: 17, date: "2023-02-09", age: 12, position: "A"))],
20: [FinalModel(first: nil, second: SecondModel(id: 20, date: "2023-02-09", age: 12, position: "A"))]
],
"2023-02-10": [
11: [FinalModel(first: [FirstModel(id: 11, date: "2023-02-10", name: "John")], second: nil)],
14: [FinalModel(first: [FirstModel(id: 14, date: "2023-02-10", name: "Harry")], second: SecondModel(id: 14, date: "2023-02-10", age: 12, position: "A"))],
16: [FinalModel(first: nil, second: SecondModel(id: 16, date: "2023-02-10", age: 12, position: "A"))]
],
"2023-02-12": [
11: [FinalModel(first: [FirstModel(id: 11, date: "2023-02-12", name: "John")], second: SecondModel(id: 11, date: "2023-02-12", age: 12, position: "A"))],
13: [FinalModel(first: [FirstModel(id: 13, date: "2023-02-12", name: "Harry")], second: nil)],
27: [FinalModel(first: nil, second: SecondModel(id: 27, date: "2023-02-12", age: 12, position: "A"))]
],
"2023-02-13": [
11: [FinalModel(first: [FirstModel(id: 11, date: "2023-02-13", name: "John")], second: nil)],
12: [FinalModel(first: [FirstModel(id: 12, date: "2023-02-13", name: "Harry")], second: nil)]
],
"2023-02-19": [
10: [FinalModel(first: [FirstModel(id: 10, date: "2023-02-19", name: "Harry")], second: SecondModel(id: 10, date: "2023-02-19", age: 12, position: "A"))],
11: [FinalModel(first: [FirstModel(id: 11, date: "2023-02-19", name: "John")], second: nil)],
15: [FinalModel(first: nil, second: SecondModel(id: 15, date: "2023-02-19", age: 12, position: "A"))]
]
]
所以,对于每个日期(date
),
英文:
I found a similar question, but it couldn't apply in my question.
I have 2 non -equal dictionaries and want to combine them into 1, I think I will describe it with the example:
struct FirstModel: Codable {
var id: Int?
var date: String?
var name: String?
}
struct SecondModel: Codable {
var id: Int?
var date: String?
var age: String?
var position: String?
}
struct FinalModel: Codable {
var first:[FirstModel]?
var second: SecondModel?
}
// dict1: [date: [FirstModel]]
var dict1 = [
"2023-02-19": [FirstModel(id: 10, date: "2023-02-19", name: "Harry"), FirstModel(id: 11, date: "2023-02-19", name: "John")],
"2023-02-13": [FirstModel(id: 12, date: "2023-02-13", name: "Harry"), FirstModel(id: 11, date: "2023-02-13", name: "John")],
"2023-02-12": [FirstModel(id: 13, date: "2023-02-12", name: "Harry"), FirstModel(id: 11, date: "2023-02-12", name: "John")],
"2023-02-10": [FirstModel(id: 14, date: "2023-02-10", name: "Harry"), FirstModel(id: 11, date: "2023-02-10", name: "John")],
]
// dict1: [date: [SecondModel]]
var dict2 = [
"2023-02-19": [SecondModel(id: 10, date: "2023-02-19", age: 12, position: "A"), SecondModel(id: 15, date: "2023-02-19", age: 12, position: "A")],
"2023-02-09": [SecondModel(id: 20, date: "2023-02-09", age: 12, position: "A"), SecondModel(id: 17, date: "2023-02-09", age: 12, position: "A")],
"2023-02-10": [SecondModel(id: 14, date: "2023-02-10", age: 12, position: "A"), SecondModel(id: 16, date: "2023-02-10", age: 12, position: "A")],
"2023-02-12": [SecondModel(id: 27, date: "2023-02-12", age: 12, position: "A"), SecondModel(id: 11, date: "2023-02-12", age: 12, position: "A")],
"2023-02-08": [SecondModel(id: 22, date: "2023-02-08", age: 12, position: "A"), SecondModel(id: 11, date: "2023-02-08", age: 12, position: "A")]
]
And I want a new dictionary like this
// newDict: [date: [id: [FinalModel]]]
var newDict = [
"2023-02-08": [
11: [FinalModel(first: nil, second: SecondModel(id: 11, date: "2023-02-08", age: 12, position: "A"))],
22: [FinalModel(first: nil, second: SecondModel(id: 22, date: "2023-02-08", age: 12, position: "A"))]
],
"2023-02-09": [
17: [FinalModel(first: nil, second: SecondModel(id: 17, date: "2023-02-09", age: 12, position: "A"))],
20: [FinalModel(first: nil, second: SecondModel(id: 20, date: "2023-02-09", age: 12, position: "A"))]
],
"2023-02-10": [
11: [FinalModel(first: [FirstModel(id: 11, date: "2023-02-10", name: "John")], second: nil)],
14: [FinalModel(first: [FirstModel(id: 14, date: "2023-02-10", name: "Harry")], second: SecondModel(id: 14, date: "2023-02-10", age: 12, position: "A")],
16: [FinalModel(first: nil, second: SecondModel(id: 16, date: "2023-02-10", age: 12, position: "A"))]
],
"2023-02-12": [
11: [FinalModel(first: [FirstModel(id: 11, date: "2023-02-12", name: "John")], second: SecondModel(id: 11, date: "2023-02-12", age: 12, position: "A"))],
13: [FinalModel(first: [FirstModel(id: 13, date: "2023-02-12", name: "Harry")], second: nil)],
27: [FinalModel(first: nil, second: SecondModel(id: 27, date: "2023-02-12", age: 12, position: "A"))]
],
"2023-02-13": [
11: [FinalModel(first: [FirstModel(id: 11, date: "2023-02-13", name: "John")], second: nil)],
12: [FinalModel(first: [FirstModel(id: 12, date: "2023-02-13", name: "Harry")], second: nil)]
],
"2023-02-19": [
10: [FinalModel(first: [FirstModel(id: 10, date: "2023-02-19", name: "Harry")], second: SecondModel(id: 10, date: "2023-02-19", age: 12, position: "A"))],
11: [FinalModel(first: [FirstModel(id: 11, date: "2023-02-19", name: "John")], second: nil)],
15: [FinalModel(first: nil, second: SecondModel(id: 15, date: "2023-02-19", age: 12, position: "A")]
],
]
So, For each date
there are many different id
, and each id
can contain many FirstModel
and only SecondModel
. I have encountered some problems in comparing and merge them together, newdict
is what I want to display.
Any help is much appreciated. Thanks!
I think I found the solution, but the performance is not so good.
Step 1: convert dict1: [date: [FirstModel]] -> [date: [id: [FirstModel]]]
Step 2: convert dict2: [date: [SecondModel]] -> [date: [id: [SecondModel]]]
Step 3: merge dict1 & dict2 into: [date: FinalModel3(first: [id: [FirstModel]], second: [id: [SecondModel]])]
, temporarily called dict3
Step 4: then convert dict3 into: [date: [id: FinalModel2(first: [FirstModel], second: [SecondModel])]]
答案1
得分: 0
这应该可以满足您的要求:
// 检索所有日期
let allKeysDate = Set(dict1.keys).union(dict2.keys)
let output = allKeysDate.reduce(into: [String: [Int: [FinalModel]]]()) { partialOutput, currentDateKey in
let firstModels: [FirstModel]? = dict1[currentDateKey] // 获取该日期的 FirstModel
let secondModels: [SecondModel]? = dict2[currentDateKey] // 获取该日期的 SecondModel
// 根据 firstModels 和 secondModels 的 id 获取所有 id
let allIds: Set<Int> = Set(firstModels?.compactMap { $0.id } ?? []).union(secondModels?.compactMap { $0.id } ?? [])
// 创建模型
let models: [Int: [FinalModel]] = allIds.reduce(into: [Int: [FinalModel]]()) { partialModelResult, currentIdKey in
let first: [FirstModel] = firstModels?.filter { $0.id == currentIdKey } ?? [] // 获取所有该 id 的 FirstModel
let second: [SecondModel]? = secondModels?.filter { $0.id == currentIdKey } // 获取所有该 id 的 SecondModel
// 我假设每个 id 只有一个 SecondModel(参见 `second?.first`),如果不是,您需要决定行为
let finalModel = FinalModel(first: first.isEmpty ? nil : first, second: second?.first)
var currentlySaved = partialModelResult[currentIdKey, default: []]
currentlySaved.append(finalModel)
partialModelResult[currentIdKey] = currentlySaved
}
// 设置 currentDate 的值
partialOutput[currentDateKey] = models
}
print(output)
请注意,这是对给定代码的简单中文翻译,不包括代码的详细解释。如果您需要进一步的解释或帮助,请随时提出。
英文:
This should do the trick:
// Retrieve all dates
let allKeysDate = Set(dict1.keys).union(dict2.keys)
let output = allKeysDate.reduce(into: [String: [Int: [FinalModel]]]()) { partialOutput, currentDateKey in
let firstModels: [FirstModel]? = dict1[currentDateKey] //Get the firstModel for that date
let secondModels: [SecondModel]? = dict2[currentDateKey] //Get the SecondModel for that date
//Get all ids for that date, depending on the ids of firstModels & secondModels
let allIds: Set<Int> = Set(firstModels?.compactMap { $0.id } ?? []).union( secondModels?.compactMap { $0.id } ?? [])
//Create models
let models: [Int: [FinalModel]] = allIds.reduce(into: [Int: [FinalModel]]()) { partialModelResult, currentIdKey in
let first: [FirstModel] = firstModels?.filter { $0.id == currentIdKey } ?? [] //Get all FirstModel for that id
let second: [SecondModel]? = secondModels?.filter { $0.id == currentIdKey } //Get all SecondtModel for that id
//I supposed there can only be one SecondModel for each id (see `second?.first`), if not, you need to decide on the behavior
let finalModel = FinalModel(first: first.isEmpty ? nil : first, second: second?.first)
var currentlySaved = partialModelResult[currentIdKey, default: []]
currentlySaved.append(finalModel)
partialModelResult[currentIdKey] = currentlySaved
}
//Set the value for the currentDate
partialOutput[currentDateKey] = models
}
print(output)
The idea is to retrieve all the dates (allKeysDate
), iterate on them (with reduce(into:_)
), and create multiple FinalModel
according to each id
in that date.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论