In Scala, how do I track current totals without using var?

For example, suppose I want to read fat, carbohydrates and protein and want to print the current amount of each variable. The imperative style will look like this:

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) } 

How can I write above using only vals?

+6
source share
4 answers

Use 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) 
+13
source

recursion. Pass the sums from the previous line to a function that adds them to the values ​​from the current line, prints them to CSV and passes them to yourself ...

+3
source

You can convert your data using map and get the final result using sum :

 val total = allData map { ... } sum 

With scanLeft you get the specific amounts of each step:

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

If you want to create several new values ​​in one iteration step, I would prefer a class that contains values:

 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) } 
+2
source

It's just a jump to the left
and then bend to the right /:

 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 + xa, acc.b + xb, acc.c + xc)) 
0
source

Source: https://habr.com/ru/post/893403/


All Articles