F#用List.fold查找最小函数



我需要一个函数来查找实现List.fold模块的列表的最小元素。我知道我可以使用List.min,但对于这个练习,我需要它是List.fold。到目前为止,我有:

let findMin list min = function
| [ ] -> min
| head::tail ->  list |> List.fold( fun acc -> min)  //missing conditional inside fold to determine min

我不习惯函数式编程,通常在java中我会做这样的事情:

public int getMin (){
int min = head.data;
Node curr = head.next;
while (! ( curr  == NULL ) ){
if ( curr.data < min) 
min = curr.data;
curr = curr.next; 
}
return min;
}

但由于F#使用不可变常量,我无法重新分配min。我发现了用于计算或求和列表中元素的fold示例,但没有找到最小或最大元素。我在模块内部的条件逻辑方面遇到了问题,如果有人能帮助我,我将不胜感激。提前谢谢。

您不需要处理输入列表为空的情况,因为List.fold在这种情况下返回初始值。通常我们通过System.Int32.MaxValue作为初始值。

这里是长版本代码:

let min a b = if a < b then a else b
let minOfList initialValue theList =
theList
|> List.fold
(fun currentMin x ->
let newMin = min currentMin x
newMin)
initialValue
let result = minOfList System.Int32.MaxValue [34; -1; 21; 99]
printfn "%d" result // -1

和短版本代码:

let min a b = if a < b then a else b
let minOfList = List.fold min
let result = minOfList System.Int32.MaxValue [34; -1; 21; 99]
printfn "%d" result // -1

您可以使用累加器作为通常将最小值分配给的值。

对于数组的每个项,fold将累加器和当前项提供给给定的函数。该函数返回的内容将成为新的累加器值。

使用内置的min功能,您可以编写

let findMin list = List.fold min System.Int32.MaxValue list

min是应用于每个项目和累加器的函数

System.Int32.MaxValue是累加器的原始值,种子

您也可以使用List.reduce,这是相同的,但它使用列表的第一个元素作为种子。

let findMin list = List.reduce min list

理想情况下,您应该将其封装在处理空数组情况的东西中,因为fold将返回种子值,而reduce将引发异常。

fold的概念很简单:在列表上迭代一个称为folder函数的函数。在每次调用中,folder函数从列表中接收一个元素和一个状态,并返回一个更新的状态。

这与您的命令式代码非常相似:您正在对列表进行迭代,从列表中接收一个元素和变量min的旧值,每次迭代后都会有一个新值min。与命令式编程的不同之处在于,folder函数不会更改状态,而是接收一个状态并返回另一个状态,可以想象,如果您喜欢List.fold在内部更改变量。

fold的签名是:

List.fold :
folder: 'State -> 'T -> 'State ->
state : 'State  ->
list  : 'T list 
-> 'State

第一个参数是文件夹函数,第二个参数是初始状态,第三个参数是元素列表。结果将是最后一个状态。

所以你的folder函数应该是这样的:

let folder min currData = ...

你的minimum函数应该是这样的:

let minimum ls =
ls
|> List.fold folder initial

你这样称呼它:

minimum [ 5 ; 3 ; 8]
|> printfn "%A"  // outputs: 3

关于如何处理初始值以及如果列表为空会发生什么,还有一些问题。但我会把这些留给你。

希望这能有所帮助。

感谢大家的帮助,澄清了一些概念。这是最后一个运行的代码段,输入验证是在主函数中完成的。

// this is the folder function List.fold calls, receives the current min and item
let folder a b = if a < b then a else b
// recieves a list and returns the minimum using the List.fold module
let fold  list = List.fold (fun acc elem -> folder acc elem) (List.head list) list

最新更新