scala - 块不能包含声明
问题描述
我是 Scala 的新手,并试图创建 UDF 函数,该函数将返回由我的 UDF 函数标识的串联元组字符串。
它应该看起来像这样,但这里有几个问题,它不喜欢在块之外定义变量“fine”,也不想改变作为参数传递的数量。
val calculateFines: UserDefinedFunction = udf((ids: Array[Long], values: Array[Double], amount: Double, complain_id: Long) => {
var fines
ids.indices foreach { i => {
val (id, value) = (ids(i), values(i))
val penalty = if (value > amount) amount else value
amount = amount - penalty
fines = fines + (amount, id, complain_id, penalty).toString()
if (amount <= 0)
break
}
}
return fines
})
解决方案
您可以通过一些修复使您的代码工作:
import scala.util.control.Breaks._ //we need this import to allow breaks since Scala doesn't support them out-of-box
val dysfunctional = udf((ids: Array[Long], values: Array[Double], amount: Double, complain_id: Long) => {
var fines: String = "" //you need to initalize var
var amountSum = amount //assign amount to var to allow to reassigment
breakable {
ids.indices foreach { i =>
{
val (id, value) = (ids(i), values(i))
val penalty = if (value > amount) amount else value
amountSum = amountSum - penalty
fines = fines + (amount, id, complain_id, penalty)
if (amount <= 0)
break
}
}
}
fines
})
这会起作用,但是很多人会不赞成它,因为它是非常非功能性的方法,而 Scala 鼓励编写函数式代码。您可能会尝试将其更改为以下内容:
val moreFunctional = (ids: Array[Long], values: Array[Double], amount: Double, complain_id: Long) => {
val (_, fines) = (ids, values)
.zipped // zip values and ids to single array of tuples
.toStream //change it to stream to allow lazy computation
.scanLeft((amount, "")) { //we pass tuple of amount and empty string as our initial state to scanLeft
case ((amount, fines), (id, value)) => //second argument of scanLeft is function which receives previous state and currently processed element of array
val penalty = if (value > amount) amount else value
(amount, fines + (amount, id, complain_id, penalty).toString()) //here we passs next state for next iteration of scanLeft
}
.takeWhile { //we proceed with computations as long and amount is above zero
case (amount, _) => amount > 0
}
.last //we're only interested in last state produced by scan left
fines
}
推荐阅读
- html - 在带有ejs的forEach循环中使用rowspan?
- mysql - 如何创建基于条件的 INSERT 触发器,更新或插入另一个表?
- sql - 使用现有查询创建过程时出错
- laravel - Laravel 商店(可空验证错误)
- wpf - WPF datagrid 一列作为组合框添加每一行不同的列表
- ios - Objective-C 中的作用域 NSArray
- swift - 半纬度/长三角洲,无需扩展
- arrays - 如何在 bash 中使用 echo 输出准备变量然后打印它
- javascript - 为什么 JavaScript 不执行?
- c++ - 未从实时 ETW 消费者接收 Microsoft-Windows-Kernel-Process 事件