Swift 3.0:使用枚举来解决这个问题的最佳方法是什么?

时间:2016-12-07 16:20:38

标签: swift enums swift3

说,我有一堆对象。我想根据形状或颜色过滤它们。

形状可以是正方形或三角形

enum Shape{ case Square, Triangle }

颜色可能是红色或绿色

enum Color{ case Red, Green }

我想要的是一个如下方法,它接受一个过滤器数组,可以是Shape或Color,或两者兼而有之。

func apply(_ filters: [Filter]){
   for filter in filters{
      if it's a Shape filter, apply that
      if it's a Color filter, apply that
   }
}

然后我可以按如下方式填充数组并将其传递给上面的方法:

let filters = [Shape.Triangle, Color.Green, Color.Red] // get objects which are triangle, or have color red, or have color green

我似乎无法弄清楚滤镜与形状/颜色之间的关系应该是什么,以便使其发挥作用。我尝试将它们嵌套如下,但这不起作用:

enum Filter{
    enum Shape{...}
    enum Color{...}
}

因为以下行中的类型不匹配:

let filters: [Filter] = [Filter.Shape.Square, Filter.Color.Green, Filter.Color.Red]

想法,有人吗?什么是解决这个问题的好方法?

3 个答案:

答案 0 :(得分:4)

处理案件的一种方法是使用协议。

Filter声明为协议,并使ShapeColor符合协议:

protocol Filter {}
extension Shape: Filter {}
extension Color: Filter {}

你可以这样写:

let filters: [Filter] = [Shape.Square, Color.Green, Color.Red]

func apply(_ filters: [Filter]){
    for filter in filters{
        if filter is Shape {/* apply that */}
        if filter is Color {/* apply that */}
    }
}

您可以为Filter协议定义一些方法,但这取决于您的实际用例。

答案 1 :(得分:2)

另一种选择:对过滤器使用公共枚举,其中枚举的每个大小写都包含一个关联值,即子过滤器类型(形状,颜色等)

enum Shape { 
    case square, triangle, circle
}

enum Color { 
    case red, green, blue
}

enum Filter {
    case shape(Shape)
    case color(Color)
}

示例设置:

struct Object {
    let id: Int
    let shape: Shape
    let color: Color
    init(_ id: Int, _ shape: Shape, _ color: Color) {
        self.id = id
        self.shape = shape
        self.color = color
    }
}

let bunchOfObjects = [
    Object(1, .square,   .red),     Object(2, .square,   .blue),
    Object(3, .square,   .green),   Object(3, .square,   .red),
    Object(5, .triangle, .green),   Object(4, .triangle, .blue),
    Object(7, .circle,   .red),     Object(5, .circle,   .green),
    ]

使用颜色square(AND red条件)的&&形状的示例过滤

let filters: [Filter] = [.shape(.square), .color(.red)]

let filteredObjects = bunchOfObjects.filter {
    obj in
    filters.reduce(true) {
        switch($1) {
            case .shape(let shape): return $0 && obj.shape == shape
            case .color(let color): return $0 && obj.color == color
        }
    }
}

filteredObjects.forEach { print($0.id, $0.shape, $0.color) }
/* 1 square red
   3 square red */

或者,使用OR ||条件进行过滤,对于满足filters数组中至少一个条件的对象(是正方形或红色;或两者)。

let filters: [Filter] = [.shape(.square), .color(.red)]

let filteredObjects = bunchOfObjects.filter {
    obj in
    filters.reduce(false) {
        switch($1) {
            case .shape(let shape): return $0 || obj.shape == shape
            case .color(let color): return $0 || obj.color == color
        }
    }
}

filteredObjects.forEach { print($0.id, $0.shape, $0.color) }
/* 1 square red
   2 square blue
   3 square green
   3 square red
   7 circle red */

答案 2 :(得分:1)

enum Shape {
    case square, triangle, circle
}

enum Color {
    case red, green, blue
}

struct Thing {
    var color = .red
    var shape = .square
}

let it = Thing()

let filters = [
    { return $0.color == .red },
    { return $0.shape == .square }
]
let isOk = filters.map { $0(it) }.reduce(true, combine: { $0 && $1 })