2011-01-19 28 views
11

Scrive una funzione che restituisce la somma parziale dell'elenco. per esempio. correre [1,2,3,5] è [1,3,6,11]. Scrivo questa funzione sotto la quale è sufficiente restituire la somma finale di tutti i valori tra gli elenchi. Come posso separarli uno per uno?Calcolo della somma cumulativa dell'elenco in Haskell

sumlist' xx=aux xx 0 
    where aux [] a=a 
      aux (x:xs) a=aux xs (a+x) 

risposta

9

È possibile regolare la funzione di produrre un elenco, semplicemente anteponendo a+x al risultato ad ogni passo e utilizzando la lista vuota come il caso base:

sumlist' xx = aux xx 0 
    where aux [] a = [] 
      aux (x:xs) a = (a+x) : aux xs (a+x) 

Tuttavia è più idiomatica Haskell per esprimere questo tipo di cosa come una piega o scansione.

25

Penso che si desidera una combinazione di scanl1 e (+), in modo da qualcosa come

scanl1 (+) *your list here* 

scanl1 si applicherà la funzione data attraverso un elenco, e riportare ogni valore intermedio nella lista restituita.

Come, per scrivere fuori in pseudo-codice,

scanl1 (+) [1,2,3] 

sarebbe uscita una lista come:

[1, 1 + 2, 1 + 2 + 3] 

o in altre parole,

[1, 3, 6] 

Learn You A Haskell ha molto di grandi esempi e descrizioni di scansioni, pieghe e molto altro ancora delle chicche di Haskell.

Spero che questo aiuti.

3

Mentre scanl1 è chiaramente la soluzione "canonica", è ancora istruttivo vedere come si potrebbe fare con foldl:

sumList xs = tail.reverse $ foldl acc [0] xs where 
    acc (y:ys) x = (x+y):y:ys 

O pointfree:

sumList = tail.reverse.foldl acc [0] where 
    acc (y:ys) x = (x+y):y:ys 

Qui è una brutta bestia force approach:

sumList xs = reverse $ acc $ reverse xs where 
    acc [] = [] 
    acc (x:xs) = (x + sum xs) : acc xs 

C'è una soluzione carina (ma non molto performante) utilizzando inits:

sumList xs = tail $ map sum $ inits xs 

Ancora pointfree:

sumList = tail.map sum.inits 
+0

@ sepp2k: Come si ottiene la somma degli elementi che vengono lasciati se si inizia sul lato destro dell'elenco? – Landei

+0

@Lamdei: Scusa, non stavo pensando bene. Tuttavia non essere pigro è ancora una buona ragione per non usare foldl (o il tuo approccio alla forza bruta). – sepp2k

+1

Perché "rovesciare"? 'sumList = (\' snd \ '[]). foldl (\\ (a, k) x -> (a + x, k. (a + x :))) (0, id) 'funziona bene nella direzione in avanti. – ephemient

0

correlati a un'altra domanda ho trovato in questo modo:

rsum xs = map (\(a,b)->a+b) (zip (0:(rsum xs)) xs) 

penso che sia anche abbastanza efficiente.

Problemi correlati