List F#中的一系列列表?
我必须编写一个从无限序列开始并返回如下结果的函数: 输入sq0={x0,x1,x2,x3,…xn} 输出序列->{[x0],[x0;x1],[x0;x1;x2][x0;x1;x2;x3]…} 你能帮我吗 我试过这个List F#中的一系列列表?,list,f#,sequence,List,F#,Sequence,我必须编写一个从无限序列开始并返回如下结果的函数: 输入sq0={x0,x1,x2,x3,…xn} 输出序列->{[x0],[x0;x1],[x0;x1;x2][x0;x1;x2;x3]…} 你能帮我吗 我试过这个 let rec pref sq = seq { yield [Seq.nth 0 sq] let x1 = Seq.nth 1 sq yield [x1] @ [x0] yield! pref Seq.skip 2 sq } 您可以使用功
let rec pref sq = seq {
yield [Seq.nth 0 sq]
let x1 = Seq.nth 1 sq
yield [x1] @ [x0]
yield! pref Seq.skip 2 sq
}
您可以使用功能
Seq.scan
:
let createSeq s =
s
|> Seq.scan (fun x y -> x @ [y]) []
|> Seq.skip 1
这样做效果很好,但可能更有效:
let input =
Seq.initInfinite (fun i -> sprintf "x%i" i)
let output =
input
|> Seq.mapi (fun i _ -> input |> Seq.take (i + 1) |> Seq.toList)
有点易变并没有什么错
let gen xs =
let ra = ResizeArray()
seq{ for x in xs do
ra.Add x
yield Seq.toList ra }
gen ["x0";"x1";"x2";"x3";"x4"]
|> printfn "%A"
输出:
seq [["x0"]; ["x0"; "x1"]; ["x0"; "x1"; "x2"]; ["x0"; "x1"; "x2"; "x3"]; ...]
如果你已经有了积累元素的顺序,gustavo的答案也不错 否则,这个递归定义也可以工作
let rec createSeq = Seq.scan List.append List.empty init
and init = seq {yield [1]; yield! createSeq}
let l = createSeq |> Seq.take 5 |> Seq.toArray
请注意,Sequence是一个接口,根据所使用的实现和访问模式,存在许多性能配置文件。如果性能是您所追求的,那么从时间角度和内存使用角度来看,这都是您想要的(这是编译器的精简版本): 重要的区别在于垃圾收集。此实现还将处理更大的序列(请注意,将拍摄200000个项目): 而其他实现在更小的输入上耗尽了内存(请注意,已获取20000项):
唯一的问题是它被限制在int范围内。您可以更改append to cons并添加对
Seq.map List.rev
的调用,使其更懒惰。是的,这是一个很好的提示。我只是想展示一个非常基本的解决方案。有很多方法可以优化它。我意识到你的列表与它的工作顺序相反-{[x0],[x0;x1]…}
vs{[x0],[x1;x0]…}
。如果这是一个问题,您可以更改zref:=即当前:!zref
tozref:=!zref@[ie.Current]
。您损失了很多性能(Real:00:00.290,CPU:00:00.265,GC gen0:6,gen1:2,gen2:0
2000项),但这仍然是最快的解决方案。感谢大家的回复:)非常有用!如果其中一个答案完全回答了您的问题,您应该将其标记为正确(请参见答案左侧的小复选标记)。
let scan z (source : seq<'T>) =
seq { let zref : ('T list ref) = ref z
yield !zref
use ie = source.GetEnumerator()
while ie.MoveNext() do
zref := ie.Current :: !zref
yield !zref }
let input = Seq.initInfinite (fun i -> sprintf "x%i" i)
let createSeqCustom s =
s
|> scan []
|> Seq.skip 1
> System.GC.Collect()
> let l = input |> createSeq |> Seq.take 2000 |> Seq.toArray
Real: 00:00:00.007, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
let createSeq s =
s
|> Seq.scan (fun x y -> x @ [y]) []
|> Seq.skip 1
> System.GC.Collect()
> let l2 = input |> createSeq |> Seq.take 2000 |> Seq.toArray
Real: 00:00:00.293, CPU: 00:00:00.296, GC gen0: 6, gen1: 4, gen2: 0
> System.GC.Collect()
> let l = input |> createSeqCustom |> Seq.take 200000 |> Seq.toArray
Real: 00:00:00.406, CPU: 00:00:00.406, GC gen0: 11, gen1: 5, gen2: 0
> let l2 = input |> createSeq |> Seq.take 20000 |> Seq.toArray
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
Stopped due to error