F# 列表操作入门

F#是一种强类型的函数式编程语言,它提供了对列表(List)非常优秀的支持。列表是一系列有序且不可变的元素集合,这些元素必须具有相同的类型。本文将介绍如何在 F# 中创建和操作列表。

创建列表

在 F# 中,有多种方式可以创建列表。以下是一些示例:

创建一个空列表:

let listEmpty = []

创建一个包含 1 到 10 的简单列表:

let list1 = [1 .. 10]

创建一个包含 1 到 10 之间奇数的简单列表,使用步长操作符:

let list2 = [1 .. 2 .. 10]

使用 for 循环创建列表

let list3 = [for i in 1 .. 10 -> i * 2]

打印列表:

let prettyPrint desc list = printfn desc printfn "%A" list

调用 prettyPrint 函数打印列表:

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# 中,还有更酷更强大的工具,那就是“列表推导式”。列表推导式允许通过使用几乎任何标准的 F# 功能(包括函数/循环/条件等)来创建列表。

以下是使用列表推导式构建列表的示例:

let is2 x = match x with | 2 -> "YES" | _ -> "NO"

直接产生 1 到 3 的列表:

let list1 = [yield 1; yield 2; yield 3;]

产生 1 到 20 之间,使用 Math.Pow 函数返回新数字的列表:

let list2 = [for i in 1.0 .. 20.0 do yield Math.Pow(i, 2.0)]

只产生 1 到 20 之间可以被 5 整除的数字的列表:

let list3 = [for i in 1 .. 20 do if i % 5 = 0 then yield i]

根据源整数是否等于 2,产生 YES/NO 字符串的列表:

let list4 = [for i in 1 .. 5 -> is2 i]

执行上述代码后,将得到以下结果:

一些有用的列表操作符

F#提供了多种操作符来处理列表,以下是一些示例:

使用 "::" 操作符可以将值追加到现有列表中。例如:

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

执行上述代码后,将得到以下结果:

列表模块

F# 的 List 模块是一个非常重要的模块。MSDN 文档中对 List 模块的描述非常详细。以下是一些示例,但更多信息请参考 MSDN:

MSDN 页面地址:

列表具有一些有用的属性,如下表所示:

属性 类型 描述
Head 'T 列表的第一个元素
Empty 'T list 返回适当类型的空列表的静态属性
IsEmpty bool 如果列表没有元素,则返回 true
Item 'T 指定索引处的元素(从零开始)
Length int 元素的数量
Tail 'T list 不包含第一个元素的列表

以下是属性的使用示例:

let list1 = [1; 2; 3] // 属性 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))

执行上述代码后,将得到以下结果:

列表模块中的函数

F#的 List 模块提供了大量函数,这里只介绍几个示例。更多信息请参考 MSDN:

MSDN 页面地址:

返回一个新的集合,其中只包含给定谓词返回 true 的元素。以下示例仅从列表中选择偶数以生成新列表:

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

执行上述代码后,将得到以下结果:

返回给定函数返回 true 的第一个元素。以下示例中,1 到 100 的列表包含数字 5,5 是第一个可以被 5 整除的数字,因此是返回值:

let isDivisibleBy number elem = elem % number = 0 let result = List.find (isDivisibleBy 5) [1..100]

执行上述代码后,将得到以下结果:

测试集合的所有元素是否满足给定谓词。以下示例中,整个列表需要包含 0 才能返回 true:

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])

执行上述代码后,将得到以下结果:

将给定的函数应用于集合的每个元素。传递给函数的整数表示元素的索引:

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

执行上述代码后,将得到以下结果:

使用给定的比较函数对给定的列表进行排序:

let list1 = [""; "&"; "&&"; "&&&"; "|"; "|||"; "|||"] printfn "Before sorting: " list1 |> printfn "%A" // 自定义排序函数 let sortFunction (string1: string) (string2: string) = if string1.Length > string2.Length then 1 else if string1.Length < string2.Length then -1 else 0 printfn "After sorting:\n%A" (List.sortWith sortFunction list1)

执行上述代码后,将得到以下结果:

模式匹配列表

在 F# 中,模式匹配列表也非常简单。例如:

let printIt desc x = printfn "%A %A" desc x let patternMatchAList list = match list with | head :: tail -> printIt "head=" head printIt "tail=" tail | [] -> ()

调用 patternMatchAList 函数:

patternMatchAList [1; 2; 3; 4; 5] printfn "\r\n\r\n" patternMatchAList [1; 2] printfn "\r\n\r\n" patternMatchAList [1]

执行上述代码后,将得到以下结果:

递归函数与列表

关于 F# 列表和模式匹配的讨论,如果不涉及递归,是不完整的。递归是一个将专门写一篇文章的主题,但目前让看看在 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 函数:

printList [1; 2; 3; 4; 5]
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485