Filter over List with dynamic filter parameter

scala

Solution

Basically what you want is a way to compose predicates. A predicate in this case is a function that takes an User and returns a Boolean. So the type is just User => Boolean

First of all, I would reformulate your "predicate generator methods" so that you can generate predicates. Inside some helper object:

object UserPredicates {
  def lastNameEquals(value:String)(user:User) = user.lastName == value
  def firstNameStartsWith(value:String)(user:User) = user.firstName.startsWith(value)
  ..
}

To generate the predicate firstName starts with "H", you can partially apply the firstNameStartsWith method like so:

import UserPredicates._
val p1: User => Boolean = firstNameStartsWith("H")

Then it is pretty simple to create a predicate from multiple predicates by defining methods that compose predicates. Maybe also inside 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))

Then you can do

import UserPredicates._
val condition1 = firstNameStartsWith("H")
val condition2 = lastNameEquals("Schmidt")
val combined = and(Seq(condition1, condition2))
users.filter(combined)

Or short

users.filter(and(firstNameStartsWith("H"), lastNameEquals("Schmidt")))

.

By the way: you should not use new to create case class instances. Also, you don't have to use equals to compare strings. The scala == operator will call equals and not just check for reference equality like the java == operator.

Problem

If I had a ``` case class User(var firstName: String, var lastName: String, var city: String) ``` and a list ``` 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")) ``` define something ``` val test1 = (user:User,key:String) => user.lastName.equals(key) val test2 = (user:User,key:String) => user.firstName.startsWith(key) ``` and filter ``` val test = users.filter(u => { test1(u,"Schmidt") && test2(u,"H") }) ``` This works fine. But How can I generate something that filters test1, test2 ... testn dynamicly form maybe a list? I want to have a lot of filter conditions predefined and combine them to one condition (like test1(u,"Schmidt") && test2(u,"H")) to filter my list and combine the order of filtering.

Original source