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