【问题标题】:Infinite sequence with repeating elements具有重复元素的无限序列
【发布时间】:2012-02-13 16:42:18
【问题描述】:

我需要创建一个无限序列,其中包含无限重复的元素子序列。

[1; 2; 3; 4; 1; 2; 3; 4; 1; 2; 3; 4; ...]

所以我写了这个:

let l = [1; 2; 3; 4]
let s = seq { while true do yield! l }

有没有标准的方法(功能)来做到这一点?

【问题讨论】:

    标签: f#


    【解决方案1】:

    我认为您的方法在这种情况下很好。没有内置函数来实现重复,但是如果你需要经常重复序列,你可以自己定义一个,并在Seq模块中提供:

    module Seq = 
      let repeat items = 
        seq { while true do yield! items }
    

    然后您可以很好地编写Seq.repeat [ 1 .. 4 ],就好像repeat 是标准的F# 库函数一样,因为F# IntelliSense 显示了来自Seq 模块和Seq 模块的两个函数,就好像它们是在一个单模块。

    除了您的实现之外,您还可以使用递归序列表达式,这是生成序列时另一种非常常见的模式。与函数式递归相比,使用while 在某些方面是必要的(尽管您不需要任何状态来进行简单的重复):

    let rec repeat items = 
      seq { yield! items  
            yield! repeat items }
    

    当您想在生成时保持某些状态时,这种方法会更好。例如,使用while 生成所有数字1 .. 就不是很好,因为您需要可变状态。使用递归,你可以写出同样的东西:

    let rec numbersFrom n = 
      seq { yield n
            yield! numbersFrom (n + 1) }
    

    【讨论】:

      【解决方案2】:

      我认为这没有成语,你所拥有的很好,但这里有一些替代方案。

      如果您将子序列更改为数组,则可以这样做

      let a = [|1; 2; 3; 4|]
      let s = Seq.initInfinite (fun i -> a.[i % a.Length])
      

      用你所拥有的,你也可以做

      let l = [1; 2; 3; 4]
      let s = Seq.initInfinite (fun _ -> l) |> Seq.concat
      

      但它并没有更短。

      【讨论】:

      • 这里有个问题:Seq.initInfinite 只为某些无穷大值生成无限序列。来自documentation:“迭代可以持续到 Int32.MaxValue。”
      • 它符合 Core lib 的无限定义,这是一个可用的工作定义。
      【解决方案3】:

      与丹尼尔的回答类似,但将其封装成一个函数,并假装该函数在 Seq 模块中:

      module Seq =
          let infiniteOf repeatedList = 
              Seq.initInfinite (fun _ -> repeatedList) 
              |> Seq.concat
      
      // Tests
      let intList = [1; 2; 3; 4]
      let charList = ['a'; 'b'; 'c'; 'd']
      let objList = [(new System.Object()); (new System.Object()); (new System.Object()); (new System.Object())]
      do
          Seq.infiniteOf intList |> Seq.take 20 |> Seq.iter (fun item -> printfn "%A" item)
          Seq.infiniteOf charList |> Seq.take 20 |> Seq.iter (fun item -> printfn "%A" item)
          Seq.infiniteOf objList |> Seq.take 20 |> Seq.iter (fun item -> printfn "%A" item)
      

      【讨论】:

        【解决方案4】:

        这将作为(或多或少)单线实现,而无需创建任何辅助对象。

        let s = seq { while true do
                        for i in 1 .. 4 -> i }
        

        【讨论】:

        • [1;2;3;4] 列表只是一个示例。实际上,我有一个需要从中构造序列的对象列表。
        猜你喜欢
        • 1970-01-01
        • 2019-09-09
        • 1970-01-01
        • 1970-01-01
        • 2014-02-17
        • 2013-08-26
        • 1970-01-01
        • 2020-11-07
        • 2011-05-14
        相关资源
        最近更新 更多