Как сравнить два неравных словаря, а затем добавить их в новый словарь в Swift?

Я нашел похожий вопрос, но он не подходит к моему вопросу.

У меня есть 2 неравных словаря и я хочу их объединить в 1, думаю опишу на примере:

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 существует много разных id, и каждый id может содержать много FirstModel и только SecondModel. Я столкнулся с некоторыми проблемами при сравнении и объединении их вместе, newdict это то, что я хочу отобразить.

Буду признателен за любую оказанную помощь. Спасибо!

Я думаю, что нашел решение, но производительность не так хороша.

Шаг 1: преобразовать dict1: [date: [FirstModel]] -> [date: [id: [FirstModel]]]

Шаг 2: преобразовать dict2: [date: [SecondModel]] -> [date: [id: [SecondModel]]]

Шаг 3: объедините dict1 и dict2 в: [date: FinalModel3(first: [id: [FirstModel]], second: [id: [SecondModel]])], временно названный dict3

Шаг 4: затем конвертируйте dict3 в: [date: [id: FinalModel2(first: [FirstModel], second: [SecondModel])]]

Кажется, что значение для "2023-02-10" неверно.

Omid Golparvar 18.02.2023 20:02

Я не совсем следую примеру. Откуда взялся id: 11 один? В любом случае, похоже, что Dictionary.merging(_:uniquingKeysWith:), вероятно, то, что вы ищете

Alexander 19.02.2023 02:30

@alexander это не то, что я ищу :(

solitary 19.02.2023 04:07

@solitary Пример выглядит тщательно, но, к сожалению, я не могу понять, какой логики вы пытаетесь достичь. Имена структур немного общие, их так много, что трудно понять, как именно эти вещи связаны друг с другом. Не могли бы вы попробовать уточнить это?

Alexander 19.02.2023 04:33

@alexander Я пытаюсь, но это кажется довольно окольным шагом 1: я объединяю dict1 и dict 2 в [Date: FinalModel] (где и моя FirstModel, и SecondModel являются массивами). Шаг 2: Теперь я пытаюсь преобразовать этот словарь в желаемый: newDict: [date: [id: [FinalModel]]]. Я не знаю, возможно ли это на самом деле.

solitary 19.02.2023 05:21

Вы можете иметь несколько FirstModel с одним и тем же идентификатором в один и тот же день, но можете ли вы иметь несколько SecondModel с одним и тем же идентификатором в один и тот же день?

Larme 19.02.2023 14:49

@Larme Я не думаю, что есть много SecondModel, но это не исключает возможности

solitary 19.02.2023 15:02

@JoakimDanielson Я хотел различать FirstModel и SecondModel, поэтому я разделил их на объекты

solitary 19.02.2023 15:04

Можно сделать так, может быть pastebin.com/zcyWG6Ut, но некоторые моменты неясны, и я не проверял каждый случай.

Larme 19.02.2023 15:32
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
9
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это должно помочь:

// 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)

Идея состоит в том, чтобы получить все даты (allKeysDate), перебрать их (с reduce(into:_)) и создать несколько FinalModel в соответствии с каждым id в этой дате.

Полный тестируемый код

Спасибо, этот ответ мне очень помог. Я немного изменил ваш код, чтобы он соответствовал моей проблеме. У меня также нет идентификаторов, поэтому я их разворачиваю

solitary 19.02.2023 17:27

Другие вопросы по теме