如果我有
case class User(var firstName: String, var lastName: String, var city: String)
和一个清单
val users = List(
new User("Peter", "Fox", "Berlin"),
new User("Otto", "Schmidt", "Berlin"),
new User("Carl", "Schmidt", "Berlin"),
new User("Hans", "Schmidt", "Berlin"),
new User("Hugo", "Schmidt", "Berlin"))
定义一些东西
val test1 = (user:User,key:String) => user.lastName.equals(key)
val test2 = (user:User,key:String) => user.firstName.startsWith(key)
并过滤
val test = users.filter(u => {
test1(u,"Schmidt") && test2(u,"H")
})
这很好用。但是,如何生成过滤test1,test2 ... testn动态形成列表的东西呢?我想要预先定义很多过滤条件,并将它们组合到一个条件(如test1(u,“Schmidt”)&& test2(u,“H”))来过滤我的列表并组合过滤顺序。
答案 0 :(得分:5)
基本上你想要的是一种组合谓词的方法。在这种情况下,谓词是一个接受用户并返回布尔值的函数。所以类型只是User =>布尔
首先,我将重新制定您的“谓词生成器方法”,以便您可以生成谓词。在一些辅助对象里面:
object UserPredicates {
def lastNameEquals(value:String)(user:User) = user.lastName == value
def firstNameStartsWith(value:String)(user:User) = user.firstName.startsWith(value)
..
}
要生成谓词firstName以“H”开头,您可以部分应用firstNameStartsWith方法,如下所示:
import UserPredicates._
val p1: User => Boolean = firstNameStartsWith("H")
然后通过定义组成谓词的方法,从多个谓词创建谓词非常简单。也许也在UserPredicates中:
def and(predicates:Seq[User => Boolean])(user:User) = predicates.forall(predicate => predicate(user))
def or(predicates:Seq[User => Boolean)(user:User) = predicates.exists(predicate => predicate(user))
然后你可以做
import UserPredicates._
val condition1 = firstNameStartsWith("H")
val condition2 = lastNameEquals("Schmidt")
val combined = and(Seq(condition1, condition2))
users.filter(combined)
或简短
users.filter(and(firstNameStartsWith("H"), lastNameEquals("Schmidt")))
顺便说一下:你不应该使用new来创建case类实例。此外,您不必使用equals来比较字符串。 scala ==运算符将调用equals,而不仅仅是检查引用相等性,如java ==运算符。
答案 1 :(得分:1)
我有点像使用implicits所以你可以得到这种语法:
case class User(var firstName: String, var lastName: String, var city: String)
val users = List(
new User("Peter", "Fox", "Berlin"),
new User("Otto", "Schmidt", "Berlin"),
new User("Carl", "Schmidt", "Berlin"),
new User("Hans", "Schmidt", "Berlin"),
new User("Hugo", "Schmidt", "Berlin"))
//Note that these are curried now
val filterLastName = (key: String) => (user: User) => user.lastName.equals(key)
val filterFirstNameFirstChars = (key: String) => (user: User) => user.firstName.startsWith(key)
implicit class FilterHelper[A](l: List[A]) {
def filter(filters: List[A => Boolean]): List[A] = {
l.filter(a => filters.forall(f => f(a)))
}
}
//implicit filter takes a list of user predicates
val test = users.filter(List(
filterLastName("Schmidt"),
filterFirstNameFirstChars("H")))