f#运行总计序列

时间:2011-03-29 21:19:06

标签: f# functional-programming

好的,这看起来应该很容易,但我只是没有得到它。如果我有一系列数字,我如何生成由运行总计组成的新序列?例如,对于序列[1; 2; 3; 4],我想将其映射到[1; 3; 6; 10]。以适当的功能方式。

5 个答案:

答案 0 :(得分:15)

使用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"

答案 1 :(得分:13)

使用Seq.scan的另一种变体(Seq.skip 1摆脱了前导零):

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

答案 2 :(得分: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)。

答案 3 :(得分:0)

不确定这是最好的方法,但应该这样做

  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

答案 4 :(得分:0)

我认为有必要与Record Types分享如何做到这一点,以防您也是来这里寻找的。

下面是一个虚构的示例,使用围绕轨道的跑步者圈来演示这一概念。

type Split = double
type Lap = { Num : int; Split : Split }
type RunnerLap = { Lap : Lap; TotalTime : double }

let lap1 = { Num = 1; Split = 1.23 } 
let lap2 = { Num = 2; Split = 1.13 } 
let lap3 = { Num = 3; Split = 1.03 } 
let laps = [lap1;lap2;lap3]

let runnerLapsAccumulator =  
  Seq.scan 
    (fun rl l -> { rl with Lap = l; TotalTime = rl.TotalTime + l.Split }) // acumulator
    { Lap = { Num = 0; Split = 0.0 }; TotalTime = 0.0 } // initial state

let runnerLaps = laps |> runnerLapsAccumulator
printfn "%A" runnerLaps