Фильтровать массив элементов по свойству enum со связанным значением - PullRequest
0 голосов
/ 11 июля 2019
class MyClass: Decodable {

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

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

Я бы хотел отфильтровать массив из MyClass элементов, чтобы отфильтрованный массив не содержал экземпляров типа .none

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

Ответы [ 2 ]

2 голосов
/ 11 июля 2019

К сожалению, вы не можете использовать == с enum s со связанными значениями. Вам нужно использовать сопоставление с шаблоном , но это нужно сделать в операторе switch или if.

Итак, это приводит к чему-то ужасному:

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

Примечания:

  1. Вы не можете назвать свой enum Type, потому что он конфликтует со встроенным Type. Измените его на что-то вроде MyType.

  2. Это ужасно сложно использовать none как случай в обычай enum, потому что он путается (людьми) с none в опционально . Это усугубляется тем фактом, что ваше свойство type является необязательным . Здесь я развернул его силой, но это, конечно, опасно.

    Вы можете сделать:

    if case .none? = $0.type
    

    Это явно соответствует случаю none и обрабатывает nil как то, что вы хотите сохранить.

    Чтобы отфильтровать nil и .none, вы можете использовать оператор объединения nil ??:

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

    Я бы предложил объявить type как MyClass.MyType вместо MyClass.MyType?.

0 голосов
/ 11 июля 2019

Я сделал вам простой пример того, как использовать enum в вашем контексте с функцией фильтра.

enum Foo {

  case article(data: [Int])
  case link(data: [String])
  case `none`

  static func myfilter(array: [Foo]) -> [Foo]{
    var newArray:[Foo] = []
    for element in array {
      switch element {
      case .article(let article):
        newArray.append(.article(data: article))
      case .link(let link):
        newArray.append(.link(data: link))
      case .none:
        break
      }
    }
    return newArray
  }
}

let foo: [Foo] = [.article(data: [1,2,3]), .link(data: ["hello", "world"]), .none]

print(Foo.myfilter(array: foo))

Я сделал код, который вы можете скомпилировать и протестировать, вы должны изменить тип для Foo, article и link.

Если вы хотите использовать перечисление, вы должны использовать switch case.

Если вы абсолютно хотите использовать фильтр в swift, вы можете, но вам нужно реализовать протокол Sequence , который в этом случае более сложный.

Для каждого случая вашего перечисления вы должны управлять делом, которое использует концепцию сопоставление с образцом . Это очень мощный.

...