2015-03-24 6 views
5

Wir haben eine Liste von ganzen Zahlen wie: [1,4,5,6,6,7,9].Scala Partialsumme mit aktuellen und allen früheren Elementen in der Liste

Die Idee ist, eine Liste mit der gleichen Länge zu generieren und bis zum aktuellen Element wie folgt zusammenzufassen: [1,5,10,16,22,29,38].

In der Java-Welt würde es wie folgt aussehen:

int sum = 0; 
int[] table = {1,4,5,6,6,7,9} 
int[] res = new int[table.length] 
for(int i=0; i<table.length; i++) { 
    sum += table[i] 
    res[i] = sum 
} 

ich weiß, gibt es mehr elegante und effiziente Lösungen. Meine Frage ist, wie man so etwas in Scala besser machen kann?

Thx!

+1

Dies ist ein Duplikat von mindestens http://stackoverflow.com/questions/4469538/scala-producing-the-intermediate-Ergebnisse-of-a-fold/4469590 # 4469590. – ziggystar

Antwort

5

Sie suchen nach dem Scan-Kombinator.

List(1,4,5,6,6,7,9).scanLeft(0)(_ + _) 
res1: List[Int] = List(0, 1, 5, 10, 16, 22, 29, 38) 

Leitelements mit Schwanz entfernen, wenn ich bin mir nicht bewusst eine Version von Scan möchten, die nicht einen Anfangswert nimmt. Die Komplexität ist O (n) für diesen Typ und Sie könnten es selbst implementieren, indem Sie die Liste über einen Akkumulator und eine Liste (die frühere Akkumulatoren enthält) zusammenfalten. Letzteres nehmen Sie als Ergebnis.

2

@ uberwatch Antwort ist die richtige, aber aus Gründen der Vollständigkeit, hier ist die weitere „generische“ funktionale Lösung foldLeft mit:

val xs = Vector(1,4,5,6,6,7,9) 
val (sumList, sum) = 
    xs.foldLeft((Vector.empty[Int], 0)) { 
    case ((list, total), x) => 
     val newTotal = x + total 
     (list :+ newTotal, newTotal) 
    } 
// sumList: Vector(1, 5, 10, 16, 22, 29, 38) 
// sum: Int = 38 
+0

Sorry Pre-Kaffee, aber ist nicht ein Größenanpassung Vektor? Dies würde (abhängig von der Implementierung) dazu führen, dass log-n-Kopiervorgänge ähnlich sind. Mein Bauchgefühl sagt mir, dass das Aufnehmen einer Liste und das Voranstellen (!) Mit einer Rückwärtsbewegung schneller sein sollte. – uberwach

+0

Welllllllll, 'Vector's Implementierung funktioniert eigentlich nicht so. Es kopiert nicht jedes Mal die Elemente, und die amortisierten Kosten sind ["effektiv konstant"] (http://docs.scala-lang.org/overviews/collections/performance-characteristics.html). In den meisten Fällen wird es also keinen Unterschied machen. Natürlich, wenn Sie riesige Listen in engen Schleifen haben, dann, ja, * vielleicht *. Aber wenn das wirklich der Performance-Engpass wäre, würde ich einfach Ihren Java-Ansatz implementieren: 'Array's und' while'-Loops werden jedes Mal der schnellste Weg sein. – dhg

Verwandte Themen