【问题标题】:scala: Dynamically filtering with predicatesscala:使用谓词动态过滤
【发布时间】:2017-12-07 03:03:27
【问题描述】:

我有一个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 匹配的谓词似乎过于具体。然后,我必须为要过滤的每种类型的 Map 编写谓词。

【问题讨论】:

    标签: scala


    【解决方案1】:

    您可以使用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))
    

    【讨论】:

    • scala 设计师想到了一切 :)
    【解决方案2】:

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

    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)
    

    【讨论】:

    • 这很有帮助,但我不确定当我同时按 String 和 Int 过滤(即按键和值)时它会如何工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多