F# 基于运算符添加数字列表

F# 基于运算符添加数字列表,f#,functional-programming,F#,Functional Programming,我对F#真的是个新手,正在努力适应整个函数式编程的思维方式。基本上,我试图找出如何遍历一个数字列表,并在总和小于某个数字(例如200)时将它们相加 目前,我有以下几点想法: let nums = [20 .. 50] let mutable total = 0 let addUp (num, (total : byref<int>)) = if (num + total < 200) then total <- total + num for

我对F#真的是个新手,正在努力适应整个函数式编程的思维方式。基本上,我试图找出如何遍历一个数字列表,并在总和小于某个数字(例如200)时将它们相加

目前,我有以下几点想法:

let nums = [20 .. 50]
let mutable total = 0

let addUp (num, (total : byref<int>)) = 
    if (num + total < 200) then
        total <- total + num

for num in nums do
    addUp (num, &total)
让nums=[20..50]
设可变总=0
let addUp(num,(总计:byref))=
如果(数量+总数<200),则

total首先,让我们尝试避免可变变量,一种方法是创建一个递归函数,用最新的total遍历列表

let rec addUp total nums =
    match nums with
    | [] -> total
    | num::tl -> 
        let newTotal = num + total
        if newTotal < 200 then
            addUp newTotal tl
        else
            total

addUp 0 nums
由于输出的类型与输入的成员的类型相同,因此我们可以使用
List.reduce
并去掉初始状态(0)

List.reduce(乐趣总数->
设newTotal=num+total
如果新总数<200,则
新总数
其他的
全部的
)努姆斯

希望这能有所帮助。

出于教育目的,上面的答案很好,因为它可以让您看到
折叠中的确切情况

对于实际项目,最好使用现有的库函数。您甚至可以分离求和和和边界检查。考虑这一点:

let addUp threshold xs =
    xs
    |> Seq.scan (+) 0                         // line 1
    |> Seq.takeWhile (fun x -> x < threshold) // line 2
    |> Seq.last                               // line 3

// Usage:
let nums = Seq.initInfinite ( (+) 20)         // line 4
nums
|> addUp 200
|> printfn "%d"       // prints "188"
let addUp threshold xs=
xs
|>序列扫描(+)0//第1行
|>Seq.takeWhile(乐趣x->x<阈值)//第2行
|>Seq.last//第3行
//用法:
设nums=Seq.initInfinite(+)20)//第4行
努姆斯
|>加起来200
|>printfn“%d”//prints“188”
一点解释:

  • 第1行是Seq.scan(fun state x->state+x)0的缩写,因此它实际上返回一个中间和序列(
    20,41,63,
  • 在第2行中,我们只取匹配或过滤谓词的元素
  • 在第3行中,我们只取最后一个元素(与上面的过滤匹配)
  • 在第4行中,同样是对
    Seq.initInfinite(funx->20+x)
    的收缩。我冒昧地将您的数据设置为无限序列(
    20,21,22,
    ),但它仍然有效
注意,代码看起来像三个调用,但序列只计算一次

注意第2行,不要像上面那样尝试收缩。原因是
(threshold
这是错误的。但是,如果您使用
(>)threshold
,它会读起来违反直觉,令人困惑


注意,函数中没有错误检查。使用空源代码序列调用它将在
Seq处崩溃。最后

这是一个巨大的帮助。谢谢!谢谢,这是一个非常有用的答案。我仍然在努力了解整个函数范例,但你在这里澄清了很多事情。
List.reduce (fun total num ->
            let newTotal = num + total
            if newTotal < 200 then
                newTotal
            else
                total
        ) nums
let addUp threshold xs =
    xs
    |> Seq.scan (+) 0                         // line 1
    |> Seq.takeWhile (fun x -> x < threshold) // line 2
    |> Seq.last                               // line 3

// Usage:
let nums = Seq.initInfinite ( (+) 20)         // line 4
nums
|> addUp 200
|> printfn "%d"       // prints "188"