F#10:列表

任何以任何语言编写的严肃编程都将始终包含列表。 因此,您将很高兴地知道F#非常好使用其List模块支持列表。 F#中的列表是相同类型的元素的有序且不变的系列。

建立清单


F#中有几种创建列表的方法。

  • 创建一个空列表
  • 创建一个包含1到10项的简单列表
  • 创建一个列表,其奇数范围为1到10
  • 使用for循环创建一个列表。

let prettyPrint desc list = printfn desc printfn "%A" list //empty list let listEmpty = [] //simple list let list1 = [1 .. 10 ] //simple list, with step value let list2 = [1 ..2..10 ] //using for loops to create lists let list3 = [for i in 1 .. 10 -> i*2 ] prettyPrint "let listEmpty = []" listEmpty prettyPrint "let list1 = [ 1 .. 10 ]" list1 prettyPrint "let list2 = [ 1 .. 2..10 ]" list2 prettyPrint "[ for i in 1 .. 10 -> i*2 ]" list3 

图片

上面显示的最后一个示例显示了如何使用for循环创建列表,这非常酷,但是F#工具箱中有一些更酷,更强大的功能,即列表理解。

列表推导(List Comprehensions)是一种功能强大的方法,可让您使用几乎所有的标准F#(包括函数/循环/条件等)来创建列表。

让我们继续看一个如何创建列表的例子。

 let is2 x = match x with | 2 -> "YES" | _ -> "NO" //yield directly let list1 = [ yield 1; yield 2; yield 3; ] //yield numbers between 1 and 20 where we use the //Math.Pow function to return a new number let list2 = [for i in 1.0 .. 20.0 do yield Math.Pow(i,2.0) ] //yield only numbers between 1 and 20 that //can be divided by 5 let list3 = [ for i in 1 .. 20 do if i % 5 = 0 then yield i ] //yields YES/NO strings depending on //whether source int = 2 or not let list4 = [for i in 1 .. 5 -> is2 i ] 

图片

一些有用的列表运算符


缺点运算符


我们可以使用cons运算符“ ::”将值添加到现有列表中,因此假设我们拥有以下列表:

 let list1 = [1;2;3;4] let list2 = 42 :: list1 

图片

串联运算符


另一个非常有用的运算符是“ @”运算符,它允许您组合相同类型的列表。 因此,例如,如果我们有这个:

 let list1 = [1;2;3;4] let list2 = [5;6;7;8] let list3 = list1 @ list2 

图片

清单模块


当我说List模块是F#中的关键模块时,我认为我并不过分。 实际上,与F#中的其他文档相比,其MSDN文档非常出色。 因此,我认为我无法在MSDN上找到的示例中增加很多用处,但是为了方便起见,我在这里提供一些示例, 但是您应该学习MSDN以获得更多信息

属性


Head
'T
第一要素
Empty
'T list
返回指定类型的空列表
空无
布尔
true-如果列表中没有元素

'T
处于特定索引的项目
长度
整型
项目数
尾巴
'T清单
没有第一项的清单:

 let list1 = [ 1; 2; 3 ] // Properties printfn "list1.IsEmpty is %b" (list1.IsEmpty) printfn "list1.Length is %d" (list1.Length) printfn "list1.Head is %d" (list1.Head) printfn "list1.Tail.Head is %d" (list1.Tail.Head) printfn "list1.Tail.Tail.Head is %d" (list1.Tail.Tail.Head) printfn "list1.Item(1) is %d" (list1.Item(1)) 

图片

筛选条件


返回一个仅包含给定谓词返回true的集合元素的新集合。 这是一个简单的示例,该示例仅从列表中选择偶数以创建新列表

 let evenOnlyList = List.filter (fun x -> x % 2 = 0) [1; 2; 3; 4; 5; 6] 

图片

搜索(查找)


返回此函数为其返回true的第一个元素。 在此示例中,由于从1到100的列表包含5,所以5是第一个数字,该数字除以5,因此这是返回值:

图片

对于所有人(所有人)


检查集合中的所有元素是否满足给定谓词。 在此示例中,整个列表必须包含0才能获得真实的返回值。

 let isAllZeroes list = List.forall (fun elem -> elem = 0.0) list printfn "%b" (isAllZeroes [0.0; 0.0]) printfn "%b" (isAllZeroes [0.0; 1.0]) 

图片

应用于全部(Iteri)


将此功能应用于集合中的每个项目。 传递给函数的整数表示元素的索引。

 let data = ["Cats";"Dogs";"Mice";"Elephants"] data |> List.iteri (fun ix -> printfn "item %d: %s" ix) 

图片

排序依据(SortWith)


使用此比较功能对指定列表进行排序。

 let list1 = [ ""; "&"; "&&"; "&&&"; ""; "|"; "||"; "|||" ] printfn "Before sorting: " list1 |> printfn "%A" //custom sorting function let sortFunction (string1:string) (string2:string) = if (string1.Length > string2.Length) then 1 else if (string1.Length printfn "After sorting:\n%A" 

图片

列表模块中有许多有用的功能,这只是您可以找到的一小部分。

一览列表的递归


如果不谈论递归,就没有完整的列表讨论,递归是整个文章的主题,但是现在,让我们看一下编写在F#中对列表起作用的递归函数所需要的内容。

 let printIt desc x = printfn "%A %A" desc x let rec printList list = match list with | h :: t -> printIt "head=" h printIt "tail=" t printList t | [] -> () printList [1;2;3;4;5] 

注意使用rec关键字,该关键字告诉F#编译器此函数将是递归的。 如果没有此关键字,则将进行递归函数调用-您将收到一条编译错误消息,尽管错误文本不是很清楚。

图片

因此,让我们来看下面的列表[1; 2; 3; 4; 5]

图片

您可以看到一切正常,并且按预期值与空列表匹配时它将停止工作。

Source: https://habr.com/ru/post/zh-CN471998/


All Articles