说,我有一堆对象。我想根据形状或颜色过滤它们。
形状可以是正方形或三角形
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]
想法,有人吗?什么是解决这个问题的好方法?
答案 0 :(得分:4)
处理案件的一种方法是使用协议。
将Filter
声明为协议,并使Shape
和Color
符合协议:
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 })