我有几个条件可以用来过滤数组。这些条件是可选的,并存储在struct中,因为用户只能选择其中的一部分。我有一系列模型。我尝试使用过滤器方法,但是您必须为其提供非可选条件。应该采用什么方法摆脱可选参数,并将该标准添加到过滤方法中?
带有过滤选项的过滤结构
struct Filter {
var brand: String?
var price: Int?
var consuption: Int?
}
模型类
class CarOffer {
var brand: String
var price: Int
var color: String
var consumption: Int
}
这是我尝试做的,但是没有运气,因为filter.price是可选的,我不知道它是否会是。我了解我必须删除一个可选项,但是如何根据其可选性在过滤器方法中添加过滤条件?还是我选择了错误的方法?
let offers: [CarOffer] = […]
func applyFilter(filter: Filter) -> [CarOffer] {
let filteredOffers = offers.filter { $0.brand == filter.brand && $0.price <= filter.price && $0.consumption <= filter.consumption }
return filteredOffers
}
答案 0 :(得分:2)
通过将代码简化和分解成较小的部分,您会更轻松。没有理由为什么在某些条件下过滤数组的函数也必须负责确定元素是否满足这些条件。您在思维上陷入了陷阱,以为过滤谓词在闭合中是&&
条件的一长链。
struct CarOffer {
let brand: String
let price: Int
let color: String
let consumption: Int
}
struct CarFilter {
let brand: String?
let price: Int?
let consumption: Int?
func matches(car: CarOffer) -> Bool {
if let brand = self.brand, brand != car.brand { return false }
if let price = self.price, price != car.price { return false }
if let consumption = self.consumption, consumption != car.consumption { return false }
return true
}
}
extension Sequence where Element == CarOffer {
func filter(carFilter: CarFilter) -> [CarOffer] {
return self.filter(carFilter.matches)
}
}
let filter = CarFilter(brand: nil, price: nil, consumption: nil)
let offers: [CarOffer] = [] //...
let filteredOffers = offers.filter(carFilter: filter)
答案 1 :(得分:0)
您可以简单地使用默认值代替filter
的可选值。如果您使用offer
的默认值,则filter
会在可选属性为nil的情况下简单地返回true。
func applyFilter(filter: Filter) -> [CarOffer] {
let filteredOffers = offers.filter { $0.brand == filter.brand && $0.price <= (filter.price ?? $0.price) && $0.consumption <= (filter.consumption ?? $0.consumption) }
return filteredOffers
}
答案 2 :(得分:0)
您可以将过滤器转换为闭包,并添加一个初始值设定项,以便轻松通过我们不关心的过滤器:
struct Filter {
var brand: (String) -> Bool
var price: (Int) -> Bool
var consuption: (Int) -> Bool
init(brand: @escaping (String) -> Bool = { _ in return true },
price: @escaping (Int) -> Bool = { _ in return true },
consuption: @escaping (Int) -> Bool = { _ in return true }) {
self.brand = brand
self.price = price
self.consuption = consuption
}
}
这提供了最大的灵活性,因为从那时起您可以添加所需的任何类型的过滤。就像根据原始结构添加文件管理器一样,忽略字段的可选选项:
init(brand: String? = nil,
price: Int? = nil,
consuption: Int? = nil) {
self.brand = { brand == nil || brand == $0 }
self.price = { price == nil || price! <= $0 }
self.consuption = { consuption == nil || consuption! <= $0 }
}