F#使用List.fold

时间:2018-10-29 02:27:32

标签: list functional-programming f#

我需要一个函数,该函数查找实现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示例,但没有一个示例可以找到最小或最大元素。我在模块内部的条件逻辑方面遇到了麻烦,如果有人可以帮助我,我将不胜感激。预先谢谢你。

4 个答案:

答案 0 :(得分:1)

您不需要处理输入列表为空的情况,因为在这种情况下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

答案 1 :(得分:0)

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

这与命令式代码非常相似:正在遍历一个列表,从列表中接收一个元素和变量min的旧值,并且在每次迭代之后,您都有一个新值{{1} }。命令式编程的区别在于min函数不会更改状态,而是收到一个并返回另一个,您可以想象是否喜欢folder在内部更改变量。

折叠的签名是:

List.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

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

希望这会有所帮助。

答案 2 :(得分:0)

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

对于数组的每个项目,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将引发异常。

答案 3 :(得分:0)

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

//这是文件夹函数List.fold调用,接收当前的分钟和项目

让文件夹a b =如果a

//接收列表并使用List.fold模块返回最小值

折叠列表=     List.fold(有趣的权限->文件夹权限)(List.head列表)列表