2011-07-23 7 views
6

Załóżmy na przykład, że chcę czytać tłuszcz, węglowodany i białko i chcę wydrukować bieżącą sumę każdej zmiennej. Tryb nadrzędny będzie wyglądał następująco:W Scala, w jaki sposób mogę śledzić bieżące sumy bez używania 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) 

} 

Jak napisać powyższe przy użyciu tylko vals?

Odpowiedz

13

Użyj 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

Rekursja. Przekaż sumy z poprzedniego wiersza do funkcji, która doda je do wartości z bieżącego wiersza, wydrukuj je do pliku CSV i przekaż do siebie ...

2

można przekształcić swoje dane z map i uzyskać całkowity wynik z sum:

val total = allData map { ... } sum 

Z scanLeft można uzyskać konkretne sumy każdym kroku:

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

Jeśli chcesz Aby utworzyć kilka nowych wartości w jednym kroku iteracji, wolałbym klasę, która zawiera wartości:

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

To tylko skok w lewo,
a następnie rozkładane w prawo /:

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)) 
Powiązane problemy