scala中条件过滤和排序的功能方式

F0R*_*0RR 6 functional-programming scala

我想对序列进行排序和/或过滤.基本上是这样的:

var result = getReallyLongSeq() // returns Seq[SomeClass]

if (doFilter) {
  result = result.filter( ... )
}

if (doSort) {
  result = result.sortWith( ... )
}
Run Code Online (Sandbox Code Playgroud)

现在,这是一种明显有效的方法,但是有更实用的方法吗?

pag*_*_5b 1

如果没有库支持,您可以推出自己的Boolean Reader Monad

这是功能性的、纯粹的、可配置的

布尔阅读器

case class BoolConf[A](run: Boolean => A) {
    def apply(b: Boolean) = run(b)
    def map[B](f: A => B): BoolConf[B] = BoolConf(b => f(run(b)))
    def flatMap[B](f: A => BoolConf[B]): BoolConf[B] = BoolConf(b => f(run(b))(b))
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们为 a 制作了一个Boolean => A允许单子组合的包装器,并且它可能已经在某些库中实现,例如scalaz

对于本例,我们只对run方法感兴趣,但您可以对其他机会感兴趣。

配置过滤和排序

然后我们包装过滤器并使用以下命令进行排序检查Reader

val mFilter: Seq[SomeClass] => BoolConf[Seq[SomeClass]] = seq => BoolConf(if(_) seq.filter(...) else seq)
val mSort: Seq[SomeClass] => BoolConf[Seq[SomeClass]] = seq => BoolConf(if(_) seq.sortWith(...) else seq)
Run Code Online (Sandbox Code Playgroud)

起重

现在,要组合这些函数,由于输出不再是简单的Seq,我们需要将其中一个函数提升为在BoolConf

def lift2Bool[A, B]: (A => B) => (BoolConf[A] => BoolConf[B]) =
    fun => cfg => BoolConf(bool => fun(cfg(bool)))
Run Code Online (Sandbox Code Playgroud)

现在我们可以将任何函数从 转换A => B提升函数BoolConf[A] => BoolConf[B]

构成

现在我们可以进行函数式的组合:

val filterAndSort = lift2Bool(mSort) compose mFilter
//or the equivalent
val filterAndSort = mFilter andThen lift2Bool(mSort)
//applies as in filterAndSort(<sequence>)(<do filter>)(<do sort>)
Run Code Online (Sandbox Code Playgroud)

还有更多

我们还可以为我们的mFilter和创建一个通用的“构建器”mSort

val configFilter[SomeClass]: (SomeClass => Boolean) => Seq[MyClass] => BoolConf[Seq[SomeClass]] = 
    filterer => seq => BoolConf(if(_) seq.filter(filterer))
Run Code Online (Sandbox Code Playgroud)

你可以自己“排序”排序等价物

感谢 Runar 的启发