2015-03-24 6 views
5

Mamy listę takich liczb całkowitych jak: [1,4,5,6,6,7,9].Scala suma częściowa z bieżącymi i wszystkimi przeszłymi elementami na liście

Chodzi o to, aby wygenerować listę o tej samej długości i sumach do bieżącego elementu, takiego jak: [1,5,10,16,22,29,38].

W świecie Javy to będzie wyglądać:

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 
} 

wiem istnieją bardziej eleganckie i wydajne rozwiązania. Moje pytanie brzmi: jak zrobić coś takiego w Scali w bardziej funkcjonalny sposób?

Thx!

+1

To jest duplikatem przynajmniej http://stackoverflow.com/questions/4469538/scala-producing-the-intermediate-results-of-a fold/4469590 # 4469590. – ziggystar

Odpowiedz

5

Poszukujesz kombinatora skanów.

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

Usuń wiodący element z ogonem, jeśli chcesz Nie jestem świadomy wersji skanowania, która nie przyjmuje wartości początkowej. Złożoność jest dla tego gościa O (n) i możesz ją zaimplementować samodzielnie, składając listę przez akumulator i listę (zawierającą poprzednie akumulatory). Ten ostatni bierzesz w rezultacie.

2

@ odpowiedź uberwatch jest słuszna, ale przez wzgląd na kompletność, tutaj jest bardziej „rodzajowe” rozwiązanie funkcjonalne używając foldLeft:

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

Przepraszam, przed kawy, ale nie jest wektorem tablicy zmiany rozmiaru? Doprowadziłoby to (w zależności od implementacji) do polubienia operacji log n copy. Moje przeczucie mówi mi, że zrobienie listy i przygotowanie (!) Z odwrotnością później powinno być szybsze. – uberwach

+0

Welllllllll, 'Implementacja Vectora faktycznie nie działa w ten sposób. Nie kopiuje elementów za każdym razem, a zamortyzowany koszt jest ["faktycznie stały"] (http://docs.scala-lang.org/overviews/collections/performance-characteristics.html). Tak więc w większości przypadków nie ma to znaczenia. Oczywiście, jeśli masz duże listy w ciasnych pętlach, to, tak, * może *. Ale jeśli to było naprawdę wąskie gardło wydajności, po prostu zaimplementowałem twoje podejście do java: pętle "Array's" i 'while' będą za każdym razem najszybsze. – dhg

Powiązane problemy