我想链接一堆过滤器,但不希望与创建多个列表相关的开销。
type StringFilter = (String) => Boolean
def nameFilter(value: String): StringFilter =
(s: String) => s == value
def lengthFilter(length: Int): StringFilter =
(s: String) => s.length == length
val list = List("Apple", "Orange")
问题是这会在每个过滤器之后构建一个列表:
list.filter(nameFilter("Apples")).filter(lengthFilter(5))
// list of string -> list of name filtered string -> list of name and length filtered string
我想:
// list of string -> list of name and length filtered string
我发现在运行时需要哪些过滤器,所以我必须动态添加过滤器。
// Not sure how to implement add function.
val filterPipe: StringFilter = ???
// My preferred DSL (or very close to it)
filterPipe.add(nameFilter("Apples")
filterPipe.add(lengthFilter(5))
// Must have DSL
list.filter(filterPipe)
如何实施filterPipe
?
有没有办法在filterPipe(它本身就是一个StringFilter)中以递归方式和过滤条件一起使用?
答案 0 :(得分:4)
您可以使用withFilter
:
list.withFilter(nameFilter("Apples")).withFilter(lengthFilter(5))...
答案 1 :(得分:1)
A blog post建议另一种使用隐式类的替代方法,以允许使用自定义运算符聚合多个谓词
implicit class Predicate[A](val pred: A => Boolean) {
def apply(x: A) = pred(x)
def &&(that: A => Boolean) = new Predicate[A](x => pred(x) && that(x))
def ||(that: A => Boolean) = new Predicate[A](x => pred(x) || that(x))
def unary_! = new Predicate[A](x => !pred(x))
}
然后您可以按如下方式应用谓词链
list.filter { (nameFilter("Apple") && lengthFilter(5)) (_) }
您还可以动态链接谓词
val list = List("Apple", "Orange", "Meat")
val isFruit = nameFilter("Apple") || nameFilter("Orange")
val isShort = lengthFilter(5)
list.filter { (isFruit && isShort) (_) }
正如您所看到的,与withFilter
方法相比,此方法的好处是您可以任意组合谓词
答案 2 :(得分:1)
还要考虑过滤器上的view,例如
list.view.filter(nameFilter("Apples")).filter(lengthFilter(5))
这可以防止中间集合,即list
中的每个条目都应用后续过滤器。