如何过滤Seq [PartialFunction]

时间:2016-10-04 10:09:38

标签: scala

我有一个业务规则列表,多个规则可以应用于给定的输入。

type Input = …
type Output = …
type Rule = PartialFunction[Input, Output]

我想编写计算所有有效输出的方法。我已经提出了这个实现:

def applyRules(i: Input, rules: Seq[Rule]) : Seq[Output] = {
  rules.flatMap(_.lift.apply(i))
}

有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

您的解决方案的一个建议变体(我认为是令人满意的)涉及过滤,然后映射过滤结果。这可以工作,但涉及同一个集合的两次传递,对于较小的集合可以是好的。但是,我们可以通过三种可能的进一步变体达到相同的结果:

  1. 使用collect方法:rules.collect { case r if r.isDefinedAt(i) => r(i) }
  2. 使用惰性withFilter代替filterrules.withFilter(_.isDefinedAt(i)).map(_.apply(i))
  3. 使用for理解(在语义上与上面的理解相同,但可能更具可读性):for (r <- rule if r isDefinedAt i) r(i)
  4. 这些解决方案可能产生的垃圾略少(每次调用lift都会创建一个新的函数对象实例 - here code),但是如果规则的数量很小我确信在大多数情况下这不是问题。

答案 1 :(得分:-1)

您可以使用isDefinedAt检查给定的Input是否可以应用于Rule

scala> val pf: PartialFunction[Any, Int] = { case s: String => 42 }
pf: PartialFunction[Any,Int] = <function1>

scala> pf.isDefinedAt(10)
res0: Boolean = false

scala> pf.isDefinedAt("")
res1: Boolean = true

所以你可以这样做:

val validInputs = rules.filter(_.isDefinedAt(i))
val result = validInputs.map(i)

同样PartialFunction包含方法applyOrElse, orElse, ...,这可能会提高可读性。

如果我误解了你的问题,请纠正我。