2011-07-23 6 views
6

Por ejemplo, supongamos que deseo leer en grasa, carbohidratos y proteínas y deseo imprimir el total acumulado de cada variable. Un estilo imperativo se vería así:En Scala, ¿cómo puedo realizar un seguimiento de los totales sin usar 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) 

} 

¿Cómo escribiría lo anterior utilizando solo vals?

Respuesta

13

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

Recursividad. Pase las sumas de la fila anterior a una función que las agregará a los valores de la fila actual, imprimirlas en CSV y pasarlas a sí mismo ...

2

Puede transformar sus datos con map y obtener el resultado total, con sum:

val total = allData map { ... } sum 

Con scanLeft a obtener las sumas particulares de cada paso:

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

Si desea para crear varios valores nuevos en un paso de iteración, preferiría una clase que contenga los valores:

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

Es sólo un salto a la izquierda, y luego
un pliegue hacia la derecha /:

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)) 
Cuestiones relacionadas