ios - 在Swift中合并两个结构数组

标签 ios swift

我收到来自服务器的响应,如下所示。在这里,reviewrating在单独的对象中,booking_id相同。

{
    "status": "Success",
    "records": [
        {
            "user_name": "123user",
            "review": "Ggg",
            "booking_id": "Booking_23749",
            "review_id": "review_38405",
            "status": "active"
        },
        {
            "_id": "5e0c43ea5bd0377f4cfdfa19",
            "user_name": "123user",
            "rating": 5,
            "booking_id": "Booking_23749"
        }
    ]
}

然后,我创建了一个Modal结构来存储来自服务器的数据。
struct ReviewRecord: Codable, Equatable {

    static func == (lhs: ReviewRecord, rhs: ReviewRecord) -> Bool {
        return lhs.bookingID == rhs.bookingID
    }

    let userName, review, bookingID, reviewID: String?
    let status, id: String?
    let rating: Int?

    enum CodingKeys: String, CodingKey {
        case userName = "user_name"
        case review
        case bookingID = "booking_id"
        case reviewID = "review_id"
        case status
        case id = "_id"
        case rating
    }
}

我用它作为
var reviewsData = [ReviewRecord]() // appending all data received in reviewsData

问题:如何合并两个对象以创建一个最终对象。所以基本上,我希望它像这样:
[
"review": "Ggg",
"review_id": "review_38405",
"status": "active"
"_id": "5e0c43ea5bd0377f4cfdfa19",
"user_name": "123user",
"rating": 5,
"booking_id": "Booking_23749"
]

更新

有关我实际上要实现的目标的更多详细信息:

如果json中有四个记录,如下所示:
    {
        "user_name": "123user",
        "review": "Ggg",
        "booking_id": "Booking1",
        "review_id": "review_38405",
        "status": "active"
    },
    {
        "_id": "5e0c43ea5bd0377f4cfdfa19",
        "user_name": "123user",
        "rating": 5,
        "booking_id": "Booking1"
    }, 
    {
        "user_name": "123user",
        "review": "Ggg",
        "booking_id": "Booking2",
        "review_id": "review_38405",
        "status": "active"
    },
    {
        "_id": "5e0c43ea5bd0377f4cfdfa19",
        "user_name": "123user",
        "rating": 5,
        "booking_id": "Booking2"
    }

我需要像这样合并Booking1和Booking2:
    {
        "user_name": "123user",
        "review": "Ggg",
        "booking_id": "Booking1",
        "review_id": "review_38405",
        "status": "active"
        "_id": "5e0c43ea5bd0377f4cfdfa19",
        "rating": 5,
    }, 
    {
        "user_name": "123user",
        "review": "Ggg",
        "booking_id": "Booking2",
        "review_id": "review_38405",
        "status": "active"
        "_id": "5e0c43ea5bd0377f4cfdfa19",
        "rating": 5,
    }

我希望现在已经很清楚了。

最佳答案

JSON

给定这个JSON

let data = """
{
    "status": "Success",
    "records": [
        {
            "user_name": "123user",
            "review": "Ggg",
            "booking_id": "Booking_23749",
            "review_id": "review_38405",
            "status": "active"
        },
        {
            "_id": "5e0c43ea5bd0377f4cfdfa19",
            "user_name": "123user",
            "rating": 5,
            "booking_id": "Booking_23749"
        }
    ]
}
""".data(using: .utf8)!

并给出相关的Codable结构

我们需要将merged(with:方法添加到Record结构中
struct Response: Decodable {

    let status: String
    let records: [Record]

    struct Record: Decodable {

        let userName: String?
        let review: String?
        let bookingID: String
        let reviewID: String?
        let status: String?
        let id: String?
        let rating: Int?

        enum CodingKeys: String, CodingKey {
            case userName = "user_name"
            case review
            case bookingID = "booking_id"
            case reviewID = "review_id"
            case status
            case id = "_id"
            case rating
        }

        func merged(with record: Record) -> Record? {
            guard bookingID == record.bookingID else { return nil }
            return Record(userName: userName ?? record.userName,
                          review: review ?? record.review,
                          bookingID: bookingID,
                          reviewID: reviewID ?? record.reviewID,
                          status: status ?? record.status,
                          id: id ?? record.id,
                          rating: rating ?? record.rating
            )
        }
    }
}

解码和合并

现在我们可以解码并合并具有相同Record(s)recordID
do {
    let response = try JSONDecoder().decode(Response.self, from: data)

    let mergedRecords = response
        .records
        .reduce(into: [String: Response.Record]()) { (result, record) in

            guard let existingRecord = result[record.bookingID] else {
                result[record.bookingID] = record
                return
            }

            let merged = existingRecord.merged(with: record)
            result[record.bookingID] = merged
        }
        .values


    print(mergedRecords)

} catch {
    print(error)
}

结果
[
    Response.Record(
        userName: Optional("123user"),
        review: Optional("Ggg"),
        bookingID: "Booking_23749",
        reviewID: Optional("review_38405"),
        status: Optional("active"),
        id: Optional("5e0c43ea5bd0377f4cfdfa19"),
        rating: Optional(5)
    )
]

马卡丁素

此代码适用于输入JSON的records字段中的任意数量的元素。

更新

我用您的新输入JSON测试了我的代码
let data = """
{
    "status": "Success",
    "records": [
        {
            "user_name": "123user",
            "review": "Ggg",
            "booking_id": "Booking1",
            "review_id": "review_38405",
            "status": "active"
        },
        {
            "_id": "5e0c43ea5bd0377f4cfdfa19",
            "user_name": "123user",
            "rating": 5,
            "booking_id": "Booking1"
        },
        {
            "user_name": "123user",
            "review": "Ggg",
            "booking_id": "Booking2",
            "review_id": "review_38405",
            "status": "active"
        },
        {
            "_id": "5e0c43ea5bd0377f4cfdfa19",
            "user_name": "123user",
            "rating": 5,
            "booking_id": "Booking2"
        }
    ]
}
""".data(using: .utf8)!

我得到了预期的结果
[
    Response.Record(userName: Optional("123user"),
                 review: Optional("Ggg"),
                 bookingID: "Booking1",
                 reviewID: Optional("review_38405"),
                 status: Optional("active"),
                 id: Optional("5e0c43ea5bd0377f4cfdfa19"),
                 rating: Optional(5)),
    Response.Record(userName: Optional("123user"),
                 review: Optional("Ggg"),
                 bookingID: "Booking2",
                 reviewID: Optional("review_38405"),
                 status: Optional("active"),
                 id: Optional("5e0c43ea5bd0377f4cfdfa19"),
                 rating: Optional(5))
]

因此,请仔细检查您是否完全按照我的指示进行;)

关于ios - 在Swift中合并两个结构数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59551313/

相关文章:

ios - 在带有 NSFetchRequest 的 select 语句中使用 Case

ios - 具有动态 header 的 UICollectionViewController(如 Reddit 应用程序)

ios - 渐变色 swift

iOS 8 - 搜索显示 Controller 在右侧显示空白

swift - 使用来自另一个类的参数调用 viewcontroller 中的函数

swift - Xero-Api 和 Vapor 3 无法连接到接收 token

ios - 在collectionView中拖放单元格时创建一个新部分?

ios - 归档 NSMutableArray

ios - 如何支持 iOs 9 功能,同时保持对 iOs 8 的支持?

iPhone开发: how to handle fbwebdialogs pop-up buttons