微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Take while running total 小于 value

如何解决Take while running total 小于 value

我试图生成一个偶数列表,而列表中项目的总和小于给定的数字。 例如,如果阈值 k 为 20,则预期输出为 [0;2;4;6;8]

我可以生成一个列表,其中最大值小于阈值,如下所示:

let listofEvennumbeRSSmallerThanTwenty =
    Seq.unfold (fun x -> Some(x,x + 1)) 0 // natural numbers
    |> Seq.filter (fun x -> x % 2 = 0) // even numbers
    |> Seq.takeWhile (fun x -> x <= 20)
    |> List.ofSeq

(我知道我可以将展开和过滤器组合到 Some(x,x + 2) ,但此任务用于教育目的)

我设法创建了一个运行总数小于阈值的不同列表:

let runningTotal =
    listofEvennumbeRSSmallerThanTwenty 
    |> Seq.scan (+) 0
    |> Seq.filter (fun x -> x < 20)
    |> List.ofSeq

但为了做到这一点,我在 listofEvennumbeRSSmallerThanTwenty 中设置了阈值(这比所需的项目多得多)并且我丢失了初始序列。我也确实尝试过使用可变值找到它,但并不真正喜欢那条路线。

解决方法

这是一个我认为非常优雅的解决方案(虽然不是最有效的):

let evens = Seq.initInfinite (fun i -> 2 * i)
Seq.initInfinite (fun i -> Seq.take i evens)
    |> Seq.takeWhile (fun seq ->
        Seq.sum seq <= 20)
    |> Seq.last
    |> List.ofSeq
,

您可以创建一个小的谓词函数来封装可变和。

let sumLessThan threshold =
    let mutable sum = 0
    fun x ->
        sum <- sum + x
        sum < threshold

使用非常简单,可以应用于任何序列

Seq.initInfinite ((*) 2) |> Seq.takeWhile (sumLessThan 20)

封装后使用可变状态没有什么不好的(检查Seq模块中可变变量的用法)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。