swiftfilterenumsassociated-value

Filter array of items by enum property with associated value


class MyClass: Decodable {

    let title: String?
    let type: MyClass.MyType?

    enum MyType {
        case article(data: [Article])
        case link(data: [LinkTile])
        case none
    }
}

I would like to filter an array of MyClass items, so the filtered array won't contain instances with type .none

let filteredArray = array.filter { $0.type != .none } // this doesn't work

Solution

  • Unfortunately, you can't use == with enums with associated values. You need to use pattern matching, but that needs to be done in a switch or if statement.

    So, that leads to something ugly like this:

    let filteredArray = array.filter { if case .none = $0.type! { return false }; return true }
    

    Notes:

    1. You can't name your enum Type because it conflicts with the built-in Type. Change it to something like MyType.

    2. It is terribly confusing to use none as a case in a custom enum because it gets confused (by the humans) with none in an optional. This is made worse by the fact that your type property is optional. Here I have force unwrapped it, but that is dangerous of course.

      You could do:

      if case .none? = $0.type
      

      This would match the none case explicitly and treat nil as something you want to keep.

      To filter out nil and .none, you could use the nil coalescing operator ??:

      if case .none = ($0.type ?? .none)
      

      I would suggest declaring type as MyClass.MyType instead of MyClass.MyType?.