【问题标题】:F# - Return element from sequenceF# - 从序列中返回元素
【发布时间】:2016-05-10 08:57:49
【问题描述】:

剧透警告!您将看到 projecteuler.net-Problem 7 的解决方案。

如果这是重复的,我很抱歉,但我在这里找不到相同的问题。

我在一个函数中计算一个数字序列并希望返回第 n 个数字。

let isPrime x = 
    {2..x/2}
    |> Seq.exists (fun e -> x%e=0)
    |> not

let PrimeNumber nth = 
    let unfolder a =
        a
        |> Seq.unfold (fun e -> Some(e, e+1))
        |> Seq.find isPrime
        |> fun e -> Some(e, e)

    2
    |> Seq.unfold unfolder
    |> Seq.skip (nth-1) 
    |> Seq.head

let ans = PrimeNumber 10001

ans 将始终为 2,但为什么呢?

当我用nth=10001 评估PrimeNumber 中的最后一个表达式时,会返回正确的项目。我错过了什么吗?

【问题讨论】:

    标签: f# seq


    【解决方案1】:

    问题在于您对 Seq.find 的使用。

    Seq.find,来自文档,返回条件为真的 first 元素。在这种情况下,即为 2。

    因此,您的展开器表达式将简单地生成一个无限的 2 序列,因此无论您采用什么元素,它始终是 2。

    要查看此内容,只需运行代码的 sn-p:

    2
    |> Seq.unfold unfolder
    
    //output: val it : seq<int> = seq [2; 2; 2; 2; ...]
    

    【讨论】:

    • |&gt; fun e -&gt; Some(e, e) 更改为 |&gt; fun e -&gt; Some(e, e+1) 修复了它。感谢您的提示。重新启动视觉工作室后,它没有评估到正确的解决方案。我不知道为什么它以前有效。
    • @Micha90 : 重新考虑e+1 - 这将毫无意义地测试每个偶数。
    • 你有什么建议?当我从 2 开始时,e+2 会跳过 3 作为素数。它也会产生错误的解决方案,即第 n+1 个素数。它并没有跑得更快,但我不明白为什么。我预计它会以两倍的速度运行。
    • @Micha90 :从 3 开始,手动将 2 注入序列头部;例如2 |&gt; Seq.unfold unfolder |&gt; Seq.skip (nth-1) 变为 3 |&gt; Seq.unfold unfolder |&gt; Seq.append (Seq.singleton 2) |&gt; Seq.skip (nth-1)
    【解决方案2】:

    如果你需要坚持这个解决方案,你需要 Seq.filter:

    let isPrime x = 
    {2..x/2}
    |> Seq.exists (fun e -> x%e=0)
    |> not
    
    let PrimeNumber nth = 
        let unfolder a =
           a
           |> Seq.unfold (fun e -> Some(e, e+1))
           |> Seq.filter isPrime
    
        2
        |> unfolder
        |> Seq.skip (nth-1) 
        |> Seq.item 0
    

    let ans = PrimeNumber 100 会给你 541 但正如其他更有效的解决方案在 cmets 中所避开的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-31
      相关资源
      最近更新 更多