0

I'm trying to filter an array of Deals with a status DealStaus which has a nested array of Bookings, each one with a BookingStatus. I want to filter Deals with status .won and Bookings according to the statuses given when calling the function. BookingStatus and DealStatus are both enums. Deal and Booking look like this:

public struct Deal: Decodable {
    public let identifier: String?
    public let status: DealStatus
    public let bookings: [Booking]?
}

public struct Booking: Decodable {
    public let identifier: String?
    public let status: BookingStatus
    public let startDate: Date?
    public let endDate: Date?
}

To do so I wrote the following snippet:

private func getDeals(with bookingStatus: [BookingStatus]) -> [Deal] {
    guard let user = currentUser, let deals = user.deals else { return [Deal]() } // Note: user is a class attribute

    return deals.filter { $0.status == .won && $0.bookings?.filter { bookingStatus.contains($0.status) }}

}

This does not work. The compiler gives the following error:

Optional type '[Booking]?' cannot be used as a boolean; test for '!= nil' instead

7
  • 1
    $0.bookings?.filter { bookingStatus.contains($0.status) } is an array. What is needed here is a Boolean, i,e, true or false. Commented Aug 14, 2018 at 12:12
  • You are trying to be too compact. Filter your Deals. Stop. Then, operating on that array of Deals, map to get a new array of Deals with their bookings filtered. Stop. Now return that new array. Commented Aug 14, 2018 at 12:16
  • 1
    Or create a function in Deal that does the check and returns a boolean so you could call ... && $0.checkBookings(bookingStatus) Commented Aug 14, 2018 at 12:32
  • For more help, show code! Show definitions of Deal and DealStatus and Booking and BookingStatus. Commented Aug 14, 2018 at 12:48
  • I have added the definitions of Deal and Booking Commented Aug 14, 2018 at 13:11

1 Answer 1

5

Following the instructions of @matt, I broke it down:

private func getDeals(with bookingStatus: [BookingStatus]) -> [Deal] {
    guard let user = currentUser, let deals = user.deals else { return [Deal]() }
        return deals
            .filter { $0.status == .won }
            .filter { $0.bookings?.contains(where: { bookingStatus.contains($0.status)} ) ?? false }
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.