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

时间:2012-10-25 07:59:05

标签: scala functional-programming

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

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

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

if (doSort) {
  result = result.sortWith( ... )
}

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

3 个答案:

答案 0 :(得分:4)

是否更具可读性是值得商榷的。它有点低效,但它也是纯粹的功能。这种方法也很容易扩展,而且可以维护。

val f: Seq[SomeClass] => Seq[SomeClass] = if(doFilter) _.filter(...) else identity
val s: Seq[SomeClass] => Seq[SomeClass] = if(doSort) _.sortWith(...) else identity
(s compose f)(result)

您还可以编写以下内容,这更像是OP中的代码。它的效率也略高一些(但不太通用)。

val filtered = if(doFilter) result.filter(...) else result
if(doSort) filtered.sortWith(...) else filtered

基于评论的讨论

如果出于某些原因,您更喜欢在第一个示例中使用curried函数(如注释中所述),则可以编写以下内容:

def fc(df: Boolean)(xs: Seq[SomeClass]) = if(df) _.filter(...) else identity
def sc(ds: Boolean)(xs: Seq[SomeClass]) = if(ds) _.sortWith(...) else identity
(sc(doSort) compose fc(doFilter))(result)

但是你可能会像这样进一步写下来,最后几乎与第一个例子中给出的相同:

def fc(df: Boolean)(xs: Seq[SomeClass]) = if(df) _.filter(...) else identity
def sc(ds: Boolean)(xs: Seq[SomeClass]) = if(ds) _.sortWith(...) else identity
val f = fc(doFilter)
val s = sc(doSort)
(s compose f)(result)

答案 1 :(得分:2)

您可以使用scalaz oparator |>或定义自己的:

class PipedObject[T](value: T)
{
    def |>[R](f: T => R) = f(value)
}

implicit def toPiped[T](value: T) =  new PipedObject[T](value)

(result |> (r => if (doFilter) r.filter(...) else r) 
        |> (r => if (doSort) r.sortWith(...) else r))

答案 2 :(得分: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))
}

在这里,我们为Boolean => A创建了一个允许monadic组合的包装器,它可能已经在某些库中实现,如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)

<强>起重

现在,要撰写这些函数,因为输出不再是简单的Seq,我们需要提升其中一个在{ {1}}

BoolConf

现在,我们可以将任何功能从def lift2Bool[A, B]: (A => B) => (BoolConf[A] => BoolConf[B]) = fun => cfg => BoolConf(bool => fun(cfg(bool))) 转换为提升功能从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>) mFilter

创建通用的“构建器”
mSort

您可以自行“排序”排序等效

感谢Runar的灵感