2011-03-29 33 views
5

好吧,這看起來應該很容易,但我只是沒有得到它。如果我有一系列數字,我如何生成一個由運行總數組成的新序列?例如對於序列[1; 2; 3; 4],我想將它映射到[1; 3; 6; 10]。以適當的功能方式。f#運行總數

回答

14

使用List.scan

let runningTotal = List.scan (+) 0 >> List.tail 

[1; 2; 3; 4] 
|> runningTotal 
|> printfn "%A" 

Seq.scan基於實現:

let runningTotal seq' = (Seq.head seq', Seq.skip 1 seq') ||> Seq.scan (+) 

{ 1..4 } 
|> runningTotal 
|> printfn "%A" 
+0

這是非常酷的,但我希望做一個序列而不是一個列表。 – Aidan 2011-03-29 21:33:10

+0

@Aidan:編輯添加適當的Seq.scan實現。 – ildjarn 2011-03-29 21:37:35

+0

很酷,就是那個。謝謝。 – Aidan 2011-03-29 21:47:37

5
> Seq.scan (fun acc n -> acc + n) 0 [1;2;3;4];; 
val it : seq<int> = seq [0; 1; 3; 6; ...] 

隨着名單:

> [1;2;3;4] |> List.scan (fun acc n -> acc + n) 0 |> List.tail;; 
val it : int list = [1; 3; 6; 10] 

編輯:另一種方式與序列:

let sum s = seq { 
    let x = ref 0 
    for i in s do 
     x := !x + i 
     yield !x 
} 

是的,有一個可變的變量,但我覺得它更具可讀性(如果你想獲得擺脫領先的0)。

+0

很酷,謝謝。然而,它似乎產生了一個更大的序列,初始值爲0,它是否不像真實的地圖。 – Aidan 2011-03-29 21:27:41

0

不知道這是最好的方式,但它應該使用Seq.scan做的伎倆

let input = [1; 2; 3; 4] 
    let runningTotal = 
    (input, 0) 
    |> Seq.unfold (fun (list, total) -> 
     match list with 
     | [] -> 
     None 
     | h::t -> 
     let total = total + h 
     total, (t, total) |> Some) 
    |> List.ofSeq 
13

另一個變化(Seq.skip 1擺脫領先零):

> {1..4} |> Seq.scan (+) 0 |> Seq.skip 1;; 
val it : seq<int> = seq [1; 3; 6; 10] 
+0

+1最簡單的答案呢。 – Daniel 2011-03-29 21:49:18

+2

感謝Daniel,F#爲我的病態提供了簡潔,優雅的解決方案。 – 2011-03-29 21:54:33

+1

我也是。我擔心程序員的命運與F#交織在一起。 – Daniel 2011-03-29 21:58:44