【问题标题】:Swift array in array. Using compactMap / map instead of nested loops [closed]数组中的 Swift 数组。使用 compactMap / map 而不是嵌套循环 [关闭]
【发布时间】:2019-01-14 14:56:39
【问题描述】:

我正在尝试创建一个方法的功能实现,该方法在具有嵌套循环的数组数组上进行迭代......非常不灵活。

新实现使用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 对象,然后将append 它发送到viewItems

模型的一些细节:

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

【问题讨论】:

  • 请添加所有需要的代码,以便我们运行您的示例。当前代码永远不会编译
  • 显示 CarSelectionViewItem 的声明
  • 也许使用Array.flatten(),然后只遍历结果数组?
  • 为什么要从地图主体内部附加到viewItems(而不是作为映射该值的结果返回值)?
  • booking 和 viewItems 有什么区别?如果 viewItems 已经有一些数据,您可以只映射,这会将 CarSelectionViewItems 添加到预订中,然后在循环之外执行一些操作,例如 viewItems.add(elementsOf: booking)

标签: ios arrays swift functional-programming


【解决方案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)
}

【讨论】:

    【解决方案2】:

    我想通过每个预订并创建一个CarSelectionViewItem 对象,然后将append 它发送到viewItems

    一切看起来都很好,但在这种情况下,您应该使用 forEach 来遍历所有非 nil 项,而不是 map,然后创建对象并将其附加到 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
        }
    

    【讨论】:

    • 这里的bookingsviewItems 有什么区别?
    • @DavidRönnqvist,我不知道。 gmoraleda 没有提供任何相关信息。
    • Booking 是整个对象。 CarSelectionViewItem 是用于创建视图的抽象。它的属性集有所减少。
    【解决方案3】:

    解决方案 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)
    }
    

    【讨论】:

    • 您的答案似乎可行,但不鼓励仅使用代码的答案,您应该至少添加几行来解释您提出建议的原因。
    • 感谢@EmilioPelaez 提醒我添加有关我的解决方案的简要说明。我现在已经非常简短地添加了每个解决方案的相关解释
    • 感谢您的回复。我的目标是让第一个实现正确(.forEach 仍然是一个 for 循环......)
    猜你喜欢
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 2020-09-05
    • 2019-09-10
    • 1970-01-01
    • 2022-05-12
    相关资源
    最近更新 更多