首页 > 解决方案 > 高阶滤波函数

问题描述

下面是我用来过滤列表数据的滑动窗口的代码,并且数据的每个元素都匹配一个谓词,然后过滤数据:

val data  : Map[String, List[Double]] = Map(
  "a" -> List(0.086, -0.398, -0.398, -0.312, 0.312, 0.312, 0.312, 0.312, 0.312, 0.312),
  "b" -> List(-0.119, -0.119, 1.007, 1.201, 1.201, 1.201, -1.201, 1.201, -1.201, -1.201)
)

def getChanges(f : Double => Boolean, data : Map[String, List[Double]], windowSize : Int) = {

  val result = data.map {
    case (key, value) => key -> value.sliding(windowSize).filter(_.forall(f)).toList
  }.filter {
    case (_, values) => values.nonEmpty
  }
   result
}


val threshold = 0
def f(percentChange : Double) = {
    percentChange > threshold
}

getChanges(f , data , 2).foreach(println)

印刷 :

(a,List(List(0.312, 0.312), List(0.312, 0.312), List(0.312, 0.312), List(0.312, 0.312), List(0.312, 0.312)))
(b,List(List(1.007, 1.201), List(1.201, 1.201), List(1.201, 1.201)))

这可以按预期工作,但是是否有更惯用的方式来声明和调用该函数f?阈值设置在函数之外,f这似乎是一种不好的编码习惯,因为阈值在函数之外声明,f但我不确定是否存在任何替代方案。另外我可能想介绍更复杂的过滤器逻辑,例如:

val upperThreshold = 0
val lowerThreshold = -5
def f(percentChange : Double) = {
    percentChange > lowerThreshold and percentChange <= upperThreshold
}

但同样,也许有更好的方法来实现这一点。

斯卡斯蒂:https ://scastie.scala-lang.org/PQLodmTPTvihEiYGgWAAvg

标签: scala

解决方案


getChange如果您使用第二个参数列表定义它会更好:

def getChanges(data: Map[String, List[Double]], windowSize: Int)(f: Double => Boolean) = ???

现在,您可以将过滤器定义为 lambda(好吧,公平地说,您也可以使用原始方法将其设为 lambda,只是看起来不那么漂亮),并摆脱阈值定义:

   getChanges(data , 2) { p => p >= -5 && p <= 0 }
     .foreach(println)

推荐阅读