我有一件工作正常的作品。我只是想把它转换成功能风格。问题是我将编写的集合函数用于将集合转换为值。这是用于火花流的UpdateStateByKey函数的更新方法的签名。
def updateFunction(newValues: Seq[(Int)], runningCount: Option[(Int)]): Option[(Int)] =
{
var result: Option[(Int)] = null
if(newValues.isEmpty){
result=Some(runningCount.get)
}
else
{
newValues.foreach
{ x =>
{
if(runningCount.isEmpty){
result=Some(x)
}
else
{
result=Some(x+runningCount.get)
}
}
}
}
result
}
将由此
调用val reducedRDD=keyValuelines.reduceByKey((x,y)=>(x+y))
val updatedRdd= reducedRDD.updateStateByKey(updateFunction)
如此有效
如果newValues为空,请获取runningCount。否则:
我不想使用foreach,因为它什么都不返回。所有其他收集功能似乎都不符合此标准。
我尝试将此代码转换为功能代码。有人可以确认这是正确的吗?
def updateFunctionVal(newValues: Seq[(Int)], runningCount: Option[(Int)]): Option[(Int)] = {
val result = if (newValues.isEmpty) { //check if the key is present in new batch if not then return the old values
Some(runningCount.get)
}
else {
runningCount match {
case x if runningCount.isEmpty => Some(newValues.fold(0)(_ + _))
case _ => Some(newValues.fold(0)(_ + _) + runningCount.get)
}
}
result
}
答案 0 :(得分:2)
鉴于帖子中隐藏的描述,这是使用reduceOption
的一个实现:
/*
If the newValues is empty, get the runningCount. Else:
If running count is present - sum the newValues and add runningCount
else - sum the newValues
*/
def updateFunction(newValues: Seq[(Int)], runningCount: Option[(Int)]): Option[Int] = {
newValues
.reduceOption(_ + _) // sum of values, or None
.map(_ + runningCount.getOrElse(0)) // add runningCount or 0 to sum
.orElse(runningCount) // if newValues was empty, just return runningCount
}
println(updateFunction(Seq(), Some(3))) // Some(3)
println(updateFunction(Seq(4, 5), Some(3))) // Some(12)
println(updateFunction(Seq(4, 5), None)) // Some(9)
println(updateFunction(Seq(), None)) // None
答案 1 :(得分:1)
所以只是为了清楚函数的预期输出:如果 newValues
为空,只需返回runningCount
。如果它不为空,则返回最后一个值,无论添加到runningCount
中的任何内容(如果存在)。那是对的吗?如果newValues
为空且runningCount
为None
,该怎么办?现在你抛出异常。这是一个在这种情况下返回None
的版本:
def updateFunction(newValues: Seq[Int], runningCount: Option[Int]): Option[Int] = {
newValues.lastOption match {
case None => runningCount
case Some(x) => Some(x + runningCount.getOrElse(0))
}
}
或基本相同,但更紧凑:
def updateFunction(newValues: Seq[Int], runningCount: Option[Int]): Option[Int] = {
newValues.lastOption.map(_ + runningCount.getOrElse(0)).orElse(runningCount)
}
编辑:您的第二次尝试具有完全不同的逻辑和输出。如果你用简单的英语澄清你希望函数做什么会有所帮助。
答案 2 :(得分:1)
假设我理解你试图实施的逻辑:
您有一个运行计数,以及一个应该全部添加到计数中的值列表。我相信您正在寻找的是foldLeft/Right
操作:
def update(newValues: Seq[(Int)], runningCount: Option[(Int)]) =
newValues.foldLeft[Option[(Int)]](runningCount)((count, value) =>
count match {
case Some(initial) => Some(initial + value)
case None => Some(value)
})
请注意,常规 fold
不会在这里工作,因为它只针对扩展Int
的类型定义(我认为这与关联规则有关) ,因为fold
没有定义它是从左还是右进行折叠