List F#中的一系列列表?

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 } 您可以使用功

我必须编写一个从无限序列开始并返回如下结果的函数:

输入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
}

您可以使用功能
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
to
zref:=!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