避免F#中的循环

4 f# for-loop functional-programming

我有一个字符串和数字列表,如下所示

let stringsAndNums = [("aa-",20); ("b1",20); ("aa",10); ("b12",10); ("+aa-",30)]
Run Code Online (Sandbox Code Playgroud)

我需要将列表分成一组包含在另一个中的字符串.

对于上述每个组,我必须找到最小值和最大值.

这是我试图做的:它正在工作,但我不认为这是惯用的F#,我想我应该避免for循环.

for tup in stringsAndNums do
    let subject, value = tup
    let related = 
        stringsAndNums |> List.filter( 
            fun o -> 
                       let osubject, ovalue = o; 
                       osubject.Contains(subject) || subject.Contains(osubject);
             )

    let relvalues = related |> List.map(fun o -> 
                                  let osubject, ovalue = o; 
                                  ovalue
                       )  
    let min = (relvalues |> List.min)
    let max = (relvalues |> List.max) 
    printfn "%A" (subject, value, min, max, (max - min))
Run Code Online (Sandbox Code Playgroud)

另外,如何定义返回元组结果列表而不是打印它们的函数?

期望的输出.

结果我看起来很好

("aa-", 20, 10, 30, 20)
("b1", 20, 10, 20, 10)
("aa", 10, 10, 30, 20)
("b12", 10, 10, 20, 10)
("+aa-", 30, 10, 30, 20)
Run Code Online (Sandbox Code Playgroud)

事实上,在这种情况下,两组是由

  1. +aa-值为30,aa值为10,aa-值为20,因此max为30,min为10
  2. b1值20,b12值10

我的解决方案

我现在要做的事情:现在不再有for循环了,但这段代码真的有用吗?

let results =
   stringsAndNums |> List.map(fun tup ->

//for tup in stringsAndNums do
    let subject, value = tup
    let related = 
        stringsAndNums |> List.filter( 
            fun o -> 
                       let osubject, ovalue = o; 
                       osubject.Contains(subject) || subject.Contains(osubject);
             )
    //for reltup in related do
    let relvalues = related |> List.map(fun o -> 
                                  let osubject, ovalue = o; 
                                  ovalue
                       )  
    let min = (relvalues |> List.min)
    let max = (relvalues |> List.max) 
    printfn "%A" (subject, value, min, max, (max - min))
)

for result in results do
    printf "%A" result
Run Code Online (Sandbox Code Playgroud)

The*_*Fox 6

这就是我写它的方式.

let subjectValues = [("aa-",20); ("b1",20); ("aa",10); ("b12",10); ("+aa-",30)]

let getRelated (subject, value) =
    let relValues = 
        subjectValues
        |> List.choose (fun (s, v) ->
            if s.Contains(subject) || subject.Contains(s)
            then Some v
            else None)

    let min = relValues |> List.min
    let max = relValues |> List.max

    (subject, value, min, max, (max - min))

let results = subjectValues |> List.map getRelated

printfn "%A" results
Run Code Online (Sandbox Code Playgroud)
  • 它不能用于List.map函数返回unit(类似的东西void).它产生了印刷副作用而不是价值.

  • 元组模式匹配可以直接在函数参数中完成,而不是单独完成let.

  • 我通常会尝试编写作用于单个项目的函数,然后根据需要将其与List.map一起使用,因为我发现它更干净,更灵活.

  • 我用一步替换List.map ... List.filterList.choose两者.这具有删除中间难以命名的let值的效果.

  • 我希望,我重新命名了一些值,以赋予它们更多的意义.