scala:使用谓词动态过滤

时间:2017-12-06 17:35:20

标签: scala

我有Map[String, Int]

val labelMap: mutable.HashMap[String, Int] = sparse0.sparseOperationCountRowsByTarget()

我想在一个语句中过滤该地图。过滤器可以按StringInt

进行过滤

最粗略的形式看起来像这样:

 val labelMapFiltered = labelMap.filter(label => label._1.startsWith("REL") || label._2 < 400)

现在我已经有了String和Int函数的通用实用程序谓词。字符串谓词是:

object StringPredicates
{
  def stringEquals(required:String)(input:String) = input == required
  def stringStartsWith(required:String)(input:String) = input.startsWith(required)
  def stringContains(required:String)(input:String) = input.contains(required)



  def and(predicates:Seq[String => Boolean])(input:String) = predicates.forall(predicate => predicate(input))
  def or(predicates:Seq[String => Boolean])(input:String) = predicates.exists(predicate => predicate(input))
}

Int谓词与上面的模式相同。

这允许使用以下过滤器:

val sw1=stringContains("#")
val sw2=stringStartsWith("REL")
val sw3=intGT(400)



      val labelMapFiltered = labelMap.filter( label =>sw1(label._1) || sw2(label._1) || sw3(label._2) )

我想将谓词传递给函数(作为Seq,我假设),然后过滤。 所以我正在寻找类似的东西:

val labelMapFiltered = labelMap.filter( myFunction(myPredSeq))

我可以使用已有的谓词吗?在Tuple2[String,Int]中编写与此函数中特定Map匹配的谓词似乎过于具体。然后,我必须为我想要过滤的每种类型的地图编写谓词。

2 个答案:

答案 0 :(得分:3)

您可以使用compose方法将谓词转换为接受适当的类型,例如:

val sw1: (String, Int) => Boolean = stringContains("#").compose(kv: (String, Int) => kv._1)

甚至可以做同样的事情,但映射你的谓词:

val predsOfTuples1 = predsOfStrings.map(_.compose(kv: (String, Int) => kv._1)))
val predsOfTuples2 = predsOfInts.map(_.compose(kv: (String, Int) => kv._2))
val preds = predsOfTuples1 ++ predsOfTuples2

您需要做的最后一件事是将andor方法设为通用的,这样您就可以在元组的谓词上使用它们:

def and[A](predicates:Seq[A => Boolean])(input:A) = predicates.forall(predicate => predicate(input))
def or[A](predicates:Seq[A => Boolean])(input:A) = predicates.exists(predicate => predicate(input))

答案 1 :(得分:0)

让我们简化输入并考虑一个简单的Int s列表:

List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

您可以将所有谓词放在Stream中(以便对它们进行懒惰评估,而不必评估所有谓词):

val predicates = Stream((n: Int) => n == 0, (n: Int) => n % 2 == 1, (n: Int) => n >= 8)

规则是如果数字为0,奇数或更大或等于8,则将保留数字。

现在我们要求通过查看我们的集合中是否至少有一个返回true的谓词来过滤:

list.filter(n => predicates.exists(p => p(n)))

输出是一个至少遵守其中一条规则的数字列表:

List(0, 1, 3, 5, 7, 8, 9)