繁体   English   中英

在 Scala 中,如何在不使用 var 的情况下跟踪运行总计?

[英]In Scala, how do I keep track of running totals without using var?

例如,假设我希望读取脂肪、碳水化合物和蛋白质,并希望打印每个变量的运行总计。 命令式样式如下所示:

var totalFat = 0.0
var totalCarbs = 0.0
var totalProtein = 0.0
var lineNumber = 0

for (lineData <- allData) {
    totalFat += lineData...
    totalCarbs += lineData...
    totalProtein += lineData...
    lineNumber += 1

    printCSV(lineNumber, totalFat, totalCarbs, totalProtein)

}

我将如何仅使用 vals 编写上述内容?

使用scanLeft

val zs = allData.scanLeft((0, 0.0, 0.0, 0.0)) {  case(r, c) =>
  val lineNr = r._1 + 1
  val fat = r._2 + c...
  val carbs = r._3 + c...
  val protein = r._4 + c...
  (lineNr, fat, carbs, protein)
}

zs foreach Function.tupled(printCSV)

递归。 将前一行的总和传递给 function ,它将它们添加到当前行的值中,将它们打印到 CSV 并将它们传递给自身...

您可以使用map转换数据并使用sum获得总结果:

val total = allData map { ... } sum

使用scanLeft您可以获得每个步骤的特定总和:

val steps = allData.scanLeft(0) { case (sum,lineData) => sum+lineData}
val result = steps.last

如果您想在一个迭代步骤中创建多个新值,我更喜欢包含以下值的 class:

case class X(i: Int, str: String)
object X {
  def empty = X(0, "")
}
(1 to 10).scanLeft(X.empty) { case (sum, data) => X(sum.i+data, sum.str+data) }

只是向左一跳,
然后向右折叠/:

class Data (val a: Int, val b: Int, val c: Int) 
val list = List (new Data (3, 4, 5), new Data (4, 2, 3), 
                 new Data (0, 6, 2), new Data (2, 4, 8)) 
val res = (new Data (0, 0, 0) /: list) 
  ((acc, x) => new Data (acc.a + x.a, acc.b + x.b, acc.c + x.c))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM