F#中的一系列列表?

时间:2014-06-17 12:46:53

标签: 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
}

5 个答案:

答案 0 :(得分:4)

您可以使用Seq.scan

功能
let createSeq s =
    s
    |> Seq.scan (fun x y -> x @ [y]) []
    |> Seq.skip 1

答案 1 :(得分:3)

这很有效但可能更有效率:

let input = 
    Seq.initInfinite (fun i -> sprintf "x%i" i)

let output = 
    input 
    |> Seq.mapi (fun i _ -> input |> Seq.take (i + 1) |> Seq.toList)

答案 2 :(得分:1)

有一点可变性没有错。

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"]; ...]

答案 3 :(得分:0)

如果你已经有了累积元素的序列,古斯塔沃的答案也不错。

否则,这个递归定义也可以起作用。

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是一个接口,因此根据所使用的实现和访问模式存在许多性能配置文件。

答案 4 :(得分:0)

如果性能是您之后的,那么从时间角度和内存使用角度来看,这就是您想要的(这是编译器中Seq.scan的精简版本):

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

重要的区别是垃圾收集。此实现还将处理更大的序列(注意200,000个项目):

> 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

而其他实现在更小的输入上耗尽内存(注意要采集的是20,000个项目):

> let l2 = input |> createSeq |> Seq.take 20000 |> Seq.toArray

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
Stopped due to error