如何比较两个不相等的字典,然后将它们添加到一个新的字典中在Swift中?

huangapple go评论65阅读模式
英文:

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 &amp; secondModels
    let allIds: Set&lt;Int&gt; = 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.

Full testable code

huangapple
  • 本文由 发表于 2023年2月19日 02:02:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75495334.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定