通过具有关联值的enum属性过滤项目数组

时间:2019-07-11 12:02:23

标签: swift filter enums associated-value

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 个答案:

答案 0 :(得分:2)

很遗憾,您不能将==与具有关联值的enum一起使用。您需要使用模式匹配,但这需要在switchif语句中完成。

因此,这会导致如下丑陋的事情:

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

注释:

  1. 您无法命名enum Type,因为它与内置Type冲突。将其更改为类似MyType的内容。

  2. 在自定义none中使用enum作为案例非常令人困惑,因为在 optional <中,它被({人类})与none混淆了。 / em>。您的type属性是可选的事实使情况变得更糟。在这里,我用力将其打开,但这当然很危险。

    您可以这样做:

    if case .none? = $0.type
    

    这将明确匹配none的情况,并将nil视为您想要保留的内容。

    要过滤掉nil.none,可以使用 nil合并运算符 ??

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

    我建议将type声明为MyClass.MyType,而不是MyClass.MyType?

答案 1 :(得分:0)

我为您提供了一个简单的示例,该示例说明了如何在您的上下文中通过过滤器功能使用枚举。

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

我编写了一个可以编译和测试的代码,您必须更改Fooarticlelink的类型。

要使用枚举时,必须使用switch case

如果您绝对希望迅速使用过滤器,则可以,但是您需要实现协议Sequence,在这种情况下,协议会更加复杂。

对于您的每种枚举,您都必须使用pattern matching的概念来管理一个案例。它非常强大。