Loops 如何在FSharp中中断对列表的迭代?
当第一项与条件匹配时,我想停止对列表的迭代Loops 如何在FSharp中中断对列表的迭代?,loops,f#,break,Loops,F#,Break,当第一项与条件匹配时,我想停止对列表的迭代 let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] let list2 = [1; 2; 9] list1 |> List.iter (fun item -> match List.contains item list2 with | false -> printfn " Not Present %A" item | true -&
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
let list2 = [1; 2; 9]
list1 |> List.iter (fun item ->
match List.contains item list2 with
| false -> printfn " Not Present %A" item
| true -> printfn "%A" item)
我只想打印第一个不在这里的项目,在这种情况下是3。在编写函数式代码时如何做到这一点?函数式世界中迭代的最终基础是递归:您的函数计算一些东西,然后调用自己进行下一步。或者它决定停下来,然后就不叫自己了。简单 您的特定案例非常适合此范例:
let rec loop list =
match list with
| [] -> () // no more list - just return
| head::tail ->
if List.contains head list2
then loop tail // deciding to call myself
else printfn " Not Present %A" head // deciding not to call myself
loop list1 // Kick off the process
但是国际热核实验堆呢?好吧,所有那些来自列表模块的奇特函数——包括iter——都是建立在相同的递归方案之上的。他们也决定要么在每一步都打电话,要么不打电话。对于其中一些,您可以通过参数影响决策,而对于另一些,您不能
碰巧的是,对于国际热核聚变实验堆来说,你不能。国际热核实验堆在下一步将始终调用自己,因此它将始终迭代整个列表。你对此无能为力
但是还有其他函数可以影响递归与否的决定。它们有很多,但我认为,出于您的目的,List.tryFind最合适。它采用另一个函数作为参数,该函数应返回true或false。如果返回true,tryFind将停止迭代并返回当前元素。正是你需要的
list1 |> List.tryFind (fun x ->
if List.contains x list2
then false
else printfn " Not Present %A"; true
)
函数世界中迭代的最终基础是递归:函数计算一些东西,然后为下一步调用自己。或者它决定停下来,然后就不叫自己了。简单 您的特定案例非常适合此范例:
let rec loop list =
match list with
| [] -> () // no more list - just return
| head::tail ->
if List.contains head list2
then loop tail // deciding to call myself
else printfn " Not Present %A" head // deciding not to call myself
loop list1 // Kick off the process
但是国际热核实验堆呢?好吧,所有那些来自列表模块的奇特函数——包括iter——都是建立在相同的递归方案之上的。他们也决定要么在每一步都打电话,要么不打电话。对于其中一些,您可以通过参数影响决策,而对于另一些,您不能
碰巧的是,对于国际热核聚变实验堆来说,你不能。国际热核实验堆在下一步将始终调用自己,因此它将始终迭代整个列表。你对此无能为力
但是还有其他函数可以影响递归与否的决定。它们有很多,但我认为,出于您的目的,List.tryFind最合适。它采用另一个函数作为参数,该函数应返回true或false。如果返回true,tryFind将停止迭代并返回当前元素。正是你需要的
list1 |> List.tryFind (fun x ->
if List.contains x list2
then false
else printfn " Not Present %A"; true
)
您可以利用以惰性方式计算元素的方式。在序列表达式中,使用良好的旧for循环找到所需的元素并生成它们
要模拟中断迭代,只需使用内置函数,如Seq.tryHead或Seq.take或Seq.truncate
正如您所看到的,这种方法的优点是很容易扩展以找到两个或三个符合需求的第一个元素,或所有元素
let notIn list x = list |> List.contains x |> not // just a helper function
seq { for x in list1 do
if x |> notIn list2 then yield x }
|> Seq.tryHead // or Seq.take 2 or Seq.truncate 3
|> printfn "%A"
有时,根据我的观察,使用类似命令式的方法(如for-loop)可以使代码更容易理解大多数程序员都有命令式的背景,包括我。请注意,上面的代码仍然有效。您可以利用惰性方式计算元素的方式。在序列表达式中,使用良好的旧for循环找到所需的元素并生成它们
要模拟中断迭代,只需使用内置函数,如Seq.tryHead或Seq.take或Seq.truncate
正如您所看到的,这种方法的优点是很容易扩展以找到两个或三个符合需求的第一个元素,或所有元素
let notIn list x = list |> List.contains x |> not // just a helper function
seq { for x in list1 do
if x |> notIn list2 then yield x }
|> Seq.tryHead // or Seq.take 2 or Seq.truncate 3
|> printfn "%A"
有时,根据我的观察,使用类似命令式的方法(如for-loop)可以使代码更容易理解大多数程序员都有命令式的背景,包括我。请注意,上面的代码仍然可用。您可以在此处使用tryPick。 此实现的一个优点是IO函数printfn与算法保持分离
let notPresent =
list1
|> List.tryPick
(fun item ->
if List.contains item list2
then None
else Some item)
match notPresent with
| None -> ()
| Some x -> printfn " Not Present %A" x
你可以用特里皮克。 此实现的一个优点是IO函数printfn与算法保持分离
let notPresent =
list1
|> List.tryPick
(fun item ->
if List.contains item list2
then None
else Some item)
match notPresent with
| None -> ()
| Some x -> printfn " Not Present %A" x
请记住,该算法的伸缩性很差。如果列表很大,您可能需要采用不同的算法。请记住,此算法的伸缩性较差。如果列表很大,你可能想采用不同的算法。如果我的答案对你有帮助,你会考虑接受吗?你可以点击左边灰色的勾选,如果我的回答对你有帮助,你会考虑接受吗?您可以通过单击左侧的浅灰色复选标记来完成此操作。