Is there a more elegant way of filtering a list based on optional parameter values?
def f(dates: List[Date], start: Option[Long], end: Option[Long]): List[Date] = {
(start, end) match {
case (Some(s), Some(e)) => dates filter (_.getTime > s) filter (_.getTime < e)
case (Some(s), None) => dates filter (_.getTime > s)
case (None, Some(e)) => dates filter (_.getTime < e)
case (None, None) => dates
}
}
With three optional parameter values this would have 9 cases etc.
One way would be as follows:
def f(dates: List[Date], start: Option[Long], end: Option[Long]): List[Date] =
dates.filter( d => start.map(d.getTime > _).getOrElse(true) )
.filter( d => end.map(d.getTime < _).getOrElse(true) )
or, even more succinct, you could use forall
on the options:
def f(dates: List[Date], start: Option[Long], end: Option[Long]): List[Date] =
dates.filter( d => start.forall(d.getTime > _) )
.filter( d => end.forall(d.getTime < _) )
In the case of an arbitrary amount of filters:
You could first change the parameter to List[Option[Date => Boolean]]. Then combine all filters that are actually there. Then apply the combined filter.
def f(dates : List[Date], filters : List[Option[Date => Boolean]]) = {
val combFilter = filters.foldLeft((d : Date) => true)((comb, filter) => if(filter.isDefined) (d : Date) => comb(d) && filter.get(d) else comb)
dates.filter(combFilter)
}
And assuming you have dates, start and end, you can call it like:
f(dates, List(start.map(s => _.getTime > s), end.map(e => _.getTime < e))
I think the key in your question is how to transform the parameters provided into a meaningful condition. Then you can scale up that method to any number of parameters (filtering conditions).
Using an intrinsic conversion (so, your code knows what to do with the parameter), I would approach like this:
def f(dates: List[Date], start: Option[Long], end: Option[Long]): List[Date] = {
val filters = List(start.map(x=>{y:Long=>y>x}), end.map(x=>{y:Long=>y<x})).flatten
dates.flatMap(date => if (filters.forall(filter => filter(date.getTime))) Some(date) else None)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With