数组中的Swift数组。使用compactMap / map而不是嵌套循环

时间:2018-08-07 13:34:25

标签: ios arrays swift functional-programming

我正在尝试创建一种方法的功能实现,该方法可对具有嵌套循环的数组数组进行迭代……非常麻烦。

新的实现使用compactMap展平嵌套数组,并使用map创建对象。

这是我得到的代码。我快到了,但还没有:

if !activeDeals.isEmpty {
    let carSelectionViewItems: [CarSelectionViewItem] = activeDeals
            .compactMap { $0.bookings }
            .map {
                let make = $0.vehicle?.make ?? ""
                let model = $0.vehicle?.model ?? ""
                let title = "\(make) \(model)"

                return CarSelectionViewItem(icon: $0.vehicle?.carImage ?? "",
                                                title: title,
                                                description: String(format: "car_pending_booked_description".locale,
                                                                    getNewDateStringFormat(string: $0.startDate)),
                                                bookingStatus: .active,
                                                dealStatus: .won,
                                                dealId: $0.id ?? "",
                                                showMoreFunc: {})
            }

    viewItems.append(contentsOf: carSelectionViewItems)
}

我想完成所有预订并创建一个CarSelectionViewItem对象,然后appendviewItems

模型的一些详细信息:

public struct Deal: Decodable {
    public let id: String?
    // ...
    public let bookings: [Booking]?
}

public struct Booking: Decodable {
    public let id: String?
    // ...
    public let startDate: String?
    public let vehicle: Vehicle?
}

public struct Vehicle: Decodable{
    public let id: String?
    public let licensePlate: String?
    public let make: String?
    public let model: String?
    public let version: String?
    public let ps: Double?
    public let kw: Double?
    public let fuelType: String?
    public let gearingType: String?
    public let carImage: String?
    public let manuals: String?
}

一组Deal。每笔交易都有不同的属性(id,时间戳等)和Booking数组:

[Deal1, Deal2, Deal3]

更深一层:

[[Booking1, Booking2], [Booking1, Booking2, Booking3], [Booking1]]

最终解决方案

if !activeDeals.isEmpty {
    viewItems.append(BannerViewItem(slogan: "my_car_active_request".locale.uppercased(), banner: nil))

    let carSelectionViewItem: [CarSelectionViewItem] = activeDeals
        .compactMap { $0.bookings }
        .flatMap { $0 }
        .map {
            let make = $0.vehicle?.make ?? ""
            let model = $0.vehicle?.model ?? ""
            let title = "\(make) \(model)"

            return CarSelectionViewItem(icon: $0.vehicle?.carImage ?? "",
                                        title: title,
                                        description: String(format: "car_pending_booked_description".locale,
                                                            getNewDateStringFormat(string: $0.startDate)),
                                        bookingStatus: .active,
                                        dealStatus: .won,
                                        dealId: $0.id ?? "",
                                        showMoreFunc: {})
    }

    viewItems.append(contentsOf: carSelectionViewItem)
}

3 个答案:

答案 0 :(得分:1)

我终于正确了:

if !activeDeals.isEmpty {

    let bookings = activeDeals
        .map { $0.bookings } // Gets the arrays of bookings
        .compactMap { $0 }   // Gets rid of the nils
        .flatMap { $0 }      // Flattens it

    let carSelectionViewItem: [CarSelectionViewItem] = bookings.map {
        let make = $0.vehicle?.make ?? ""
        let model = $0.vehicle?.model ?? ""
        let title = "\(make) \(model)"

        return CarSelectionViewItem(icon: $0.vehicle?.carImage ?? "",
                                            title: title,
                                            description: String(format: "car_pending_booked_description".locale,
                                                                getNewDateStringFormat(string: $0.startDate)),
                                            bookingStatus: .active,
                                            dealStatus: .won,
                                            dealId: $0.id ?? "",
                                            showMoreFunc: {})
    }

    viewItems.append(contentsOf: carSelectionViewItem)
}

答案 1 :(得分:0)

  

我想完成所有预订并创建一个CarSelectionViewItem对象,然后appendviewItems

一切都很好,但是在这种情况下,您应该使用map来遍历所有非零项目,然后创建对象并将其附加到forEach数组中,而不是viewItems

如果您真的想拥有bookings(我相信它应该是CarSelectionViewItem的数组),则应该在map中返回该对象。示例:

let bookings = activeDeals.compactMap({ $0.bookings? })
    .map {
        let make = $0.vehicle?.make ?? ""
        let model = $0.vehicle?.model ?? ""
        let title = "\(make) \(model)"

        let viewItem = CarSelectionViewItem(icon: $0.vehicle?.carImage ?? "",
                                            title: title,
                                            description: String(format: "car_pending_booked_description".locale,
                                                                getNewDateStringFormat(string: $0.startDate)),
                                            bookingStatus: .active,
                                            dealStatus: .won,
                                            dealId: $0.id ?? "",
                                            showMoreFunc: {})

        viewItems.append(viewItem)
        return viewItem
    }

答案 2 :(得分:0)

解决方案1创建一个CarSelectionViewItem的数组并将整个数组追加到viewItems中;解决方案2遍历每个预订,并将在其中创建的CarSelectionViewItem元素附加到viewItems

解决方案1:

let carSelectionViewItems = activeDeals
    .compactMap { $0.bookings }
    .map {
        let make = $0.vehicle?.make ?? ""
        let model = $0.vehicle?.model ?? ""
        let title = "\(make) \(model)"

        return CarSelectionViewItem(icon: $0.vehicle?.carImage ?? "",
                                    title: title,
                                    description: String(format: "car_pending_booked_description".locale,
                                                        getNewDateStringFormat(string: $0.startDate)),
                                    bookingStatus: .active,
                                    dealStatus: .won,
                                    dealId: $0.id ?? "",
                                    showMoreFunc: {})
    }

viewItems.append(contentsOf: carSelectionViewItems)

解决方案2:

let carSelectionViewItems = activeDeals
    .compactMap { $0.bookings }
    .forEach {
        let make = $0.vehicle?.make ?? ""
        let model = $0.vehicle?.model ?? ""
        let title = "\(make) \(model)"

        let item = CarSelectionViewItem(icon: $0.vehicle?.carImage ?? "",
                                        title: title,
                                        description: String(format: "car_pending_booked_description".locale,
                                                            getNewDateStringFormat(string: $0.startDate)),
                                        bookingStatus: .active,
                                        dealStatus: .won,
                                        dealId: $0.id ?? "",
                                        showMoreFunc: {})
        viewItems.append(item)
}