F# 中的列表是同一类型的有序、不可变的元素系列。 若要对列表执行基本作,请使用 List 模块中的函数。
创建和初始化列表
可以通过显式列出元素(用分号分隔并括在方括号中)来定义列表,如以下代码行所示。
let list123 = [ 1; 2; 3 ]
还可以在元素之间放置换行符,在这种情况下,分号是可选的。 如果元素初始化表达式较长,或者要为每个元素添加注释,则后一种语法可能会导致更可读的代码。
let list123 = [ 1; 2; 3 ]
通常,所有列表元素的类型都必须相同。 例外情况是,将元素指定为基类型的列表可以具有派生类型的元素。 因此,可以接受以下两者,因为两者都Button
CheckBox
派生自 Control
。
let myControlList: Control list = [ new Button(); new CheckBox() ]
还可以通过使用由范围运算符(..
)分隔的整数指示的范围来定义列表元素,如以下代码所示。
let list1 = [ 1..10 ]
空列表由一对方括号指定,两者之间没有任何内容。
// An empty list.
let listEmpty = []
还可以使用序列表达式创建列表。 有关详细信息,请参阅 序列表达式 。 例如,以下代码创建从 1 到 10 的整数平方列表。
let listOfSquares = [ for i in 1..10 -> i * i ]
使用列表的运算符
可以使用 (cons) 运算符将元素附加到列表 ::
。
[2; 3; 4]
如果是list1
,则以下代码将创建list2
为 [100; 2; 3; 4]
。
let list2 = 100 :: list1
可以使用运算符连接具有兼容类型的 @
列表,如以下代码所示。 如果是list1
且list2
是[100; 2; 3; 4]
,则此代码将创建list3
为 [2; 3; 4; 100; 2; 3; 4]
。[2; 3; 4]
let list3 = list1 @ list2
列表模块中提供了用于对列表执行作的函数。
由于 F# 中的列表是不可变的,因此任何修改作都生成新列表,而不是修改现有列表。
F# 中的列表实现为单向链接列表,这意味着仅访问列表头的作为 O(1),元素访问为 O(n)。
属性
列表类型支持以下属性:
资产 | 类型 | DESCRIPTION |
---|---|---|
head | 'T |
第一个元素。 |
空 | 'T list |
返回相应类型的空列表的静态属性。 |
IsEmpty | bool |
true 如果列表没有元素, |
物品 | 'T |
指定索引处的元素(从零开始)。 |
长度 | int |
元素数。 |
Tail | 'T list |
没有第一个元素的列表。 |
下面是使用这些属性的一些示例。
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))
使用列表
使用列表编程使你能够使用少量代码执行复杂作。 本部分介绍对功能编程非常重要的列表的常见作。
使用列表进行递归
列表特别适合递归编程技术。 请考虑必须在列表的每个元素上执行的作。 你可以以递归方式执行此作,方法是在列表的头上作,然后传递列表的尾部,该列表是一个较小的列表,它由没有第一个元素的原始列表组成,再次回到下一级别的递归。
若要编写此类递归函数,请在模式匹配中使用 cons 运算符 (::
),这使你可以将列表的头与尾区分开。
下面的代码示例演示如何使用模式匹配来实现对列表执行作的递归函数。
let rec sum list =
match list with
| head :: tail -> head + sum tail
| [] -> 0
前面的代码适用于小型列表,但对于较大的列表,它可能会溢出堆栈。 以下代码通过使用累加器参数改进此代码,这是使用递归函数的标准技术。 使用累加器参数会使函数尾递归,从而节省堆栈空间。
let sum list =
let rec loop list acc =
match list with
| head :: tail -> loop tail (acc + head)
| [] -> acc
loop list 0
该函数 RemoveAllMultiples
是采用两个列表的递归函数。 第一个列表包含要移除其倍数的数字,第二个列表是要从中删除数字的列表。 以下示例中的代码使用此递归函数从列表中消除所有非质数,从而将质数列表保留为结果。
let IsPrimeMultipleTest n x = x = n || x % n <> 0
let rec RemoveAllMultiples listn listx =
match listn with
| head :: tail -> RemoveAllMultiples tail (List.filter (IsPrimeMultipleTest head) listx)
| [] -> listx
let GetPrimesUpTo n =
let max = int (sqrt (float n))
RemoveAllMultiples [ 2..max ] [ 1..n ]
printfn "Primes Up To %d:\n %A" 100 (GetPrimesUpTo 100)
输出如下所示:
Primes Up To 100:
[2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71; 73; 79; 83; 89; 97]
模块函数
List 模块提供访问列表元素的函数。 head 元素是最快速、最容易访问的元素。 使用属性 Head 或模块函数 List.head。 可以使用 Tail 属性或 List.tail 函数访问列表的尾部。 若要按索引查找元素,请使用 List.nth 函数。
List.nth
遍历列表。 因此,它是 O(n)。 如果代码经常使用 List.nth
,可能需要考虑使用数组而不是列表。 数组中的元素访问为 O(1)。
列表上的布尔作
List.isEmpty 函数确定列表是否具有任何元素。
List.exists 函数将布尔测试应用于列表的元素,如果任何元素满足测试,则返回true
该测试。
List.exists2 类似,但对两个列表中的连续元素对进行作。
以下代码演示了如何使用 List.exists
。
// Use List.exists to determine whether there is an element of a list satisfies a given Boolean expression.
// containsNumber returns true if any of the elements of the supplied list match
// the supplied number.
let containsNumber number list = List.exists (fun elem -> elem = number) list
let list0to3 = [0 .. 3]
printfn "For list %A, contains zero is %b" list0to3 (containsNumber 0 list0to3)
输出如下所示:
For list [0; 1; 2; 3], contains zero is true
下面的示例演示了如何使用 List.exists2
。
// Use List.exists2 to compare elements in two lists.
// isEqualElement returns true if any elements at the same position in two supplied
// lists match.
let isEqualElement list1 list2 = List.exists2 (fun elem1 elem2 -> elem1 = elem2) list1 list2
let list1to5 = [ 1 .. 5 ]
let list5to1 = [ 5 .. -1 .. 1 ]
if (isEqualElement list1to5 list5to1) then
printfn "Lists %A and %A have at least one equal element at the same position." list1to5 list5to1
else
printfn "Lists %A and %A do not have an equal element at the same position." list1to5 list5to1
输出如下所示:
Lists [1; 2; 3; 4; 5] and [5; 4; 3; 2; 1] have at least one equal element at the same position.
如果要测试列表的所有元素是否满足条件,可以使用 List.forall 。
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])
输出如下所示:
true
false
同样, List.forall2 确定两个列表中的相应位置中的所有元素是否满足涉及每个元素对的布尔表达式。
let listEqual list1 list2 = List.forall2 (fun elem1 elem2 -> elem1 = elem2) list1 list2
printfn "%b" (listEqual [0; 1; 2] [0; 1; 2])
printfn "%b" (listEqual [0; 0; 0] [0; 1; 0])
输出如下所示:
true
false
对列表执行排序作
List.sort、List.sortBy 和 List.sortWith 函数对列表进行排序。 排序函数确定要使用的这三个函数中的哪一个。
List.sort
使用默认泛型比较。 泛型比较使用基于泛型比较函数的全局运算符来比较值。 它有效处理各种元素类型,例如简单的数值类型、元组、记录、区分联合、列表、数组和实现 System.IComparable
的任何类型。 对于实现 System.IComparable
的类型,泛型比较使用 System.IComparable.CompareTo()
函数。 泛型比较也适用于字符串,但使用与区域性无关的排序顺序。 不应对不受支持的类型(如函数类型)使用泛型比较。 此外,默认泛型比较的性能最适合小型结构化类型:对于需要频繁比较和排序的大型结构化类型,请考虑实现 System.IComparable
和提供该方法的有效 System.IComparable.CompareTo()
实现。
List.sortBy
获取一个函数,该函数返回用作排序条件的值,并将 List.sortWith
比较函数作为参数。 在处理不支持比较的类型时,或比较需要更复杂的比较语义(如区域性感知字符串的情况)时,这两个函数非常有用。
下面的示例演示了如何使用 List.sort
。
let sortedList1 = List.sort [1; 4; 8; -2; 5]
printfn "%A" sortedList1
输出如下所示:
[-2; 1; 4; 5; 8]
下面的示例演示了如何使用 List.sortBy
。
let sortedList2 = List.sortBy (fun elem -> abs elem) [1; 4; 8; -2; 5]
printfn "%A" sortedList2
输出如下所示:
[1; -2; 4; 5; 8]
下一个示例演示了如何使用 List.sortWith
。 在此示例中,自定义比较函数 compareWidgets
用于先比较自定义类型的一个字段,然后在第一个字段的值相等时再比较另一个字段。
type Widget = { ID: int; Rev: int }
let compareWidgets widget1 widget2 =
if widget1.ID < widget2.ID then -1 else
if widget1.ID > widget2.ID then 1 else
if widget1.Rev < widget2.Rev then -1 else
if widget1.Rev > widget2.Rev then 1 else
0
let listToCompare = [
{ ID = 92; Rev = 1 }
{ ID = 110; Rev = 1 }
{ ID = 100; Rev = 5 }
{ ID = 100; Rev = 2 }
{ ID = 92; Rev = 1 }
]
let sortedWidgetList = List.sortWith compareWidgets listToCompare
printfn "%A" sortedWidgetList
输出如下所示:
[{ID = 92;
Rev = 1;}; {ID = 92;
Rev = 1;}; {ID = 100;
Rev = 2;}; {ID = 100;
Rev = 5;}; {ID = 110;
Rev = 1;}]
列表上的搜索作
列表支持许多搜索作。 最简单的 List.find 使你能够找到与给定条件匹配的第一个元素。
下面的代码示例演示如何 List.find
查找列表中第一个被 5 分隔的数字。
let isDivisibleBy number elem = elem % number = 0
let result = List.find (isDivisibleBy 5) [ 1 .. 100 ]
printfn "%d " result
结果为 5。
如果元素必须首先转换,则调用 List.pick,它采用返回选项的函数,并查找第一个选项 Some(x)
值。 返回结果x
,List.pick
而不是返回元素。 如果未找到匹配的元素, List.pick
将 System.Collections.Generic.KeyNotFoundException
引发 。 以下代码演示了 List.pick
如何使用 。
let valuesList = [ ("a", 1); ("b", 2); ("c", 3) ]
let resultPick = List.pick (fun elem ->
match elem with
| (value, 2) -> Some value
| _ -> None) valuesList
printfn "%A" resultPick
输出如下所示:
"b"
另一组搜索作 List.tryFind 和相关函数返回选项值。 该 List.tryFind
函数返回满足条件的列表的第一个元素(如果存在此类元素),但如果不存在,则返回选项值 None
。 变体 List.tryFindIndex 返回元素的索引(如果找到)而不是元素本身。 以下代码说明了这些函数。
let list1d = [1; 3; 7; 9; 11; 13; 15; 19; 22; 29; 36]
let isEven x = x % 2 = 0
match List.tryFind isEven list1d with
| Some value -> printfn "The first even value is %d." value
| None -> printfn "There is no even value in the list."
match List.tryFindIndex isEven list1d with
| Some value -> printfn "The first even value is at position %d." value
| None -> printfn "There is no even value in the list."
输出如下所示:
The first even value is 22.
The first even value is at position 8.
列表上的算术运算
常见算术运算(如 sum 和 average)内置于 List 模块中。 若要使用 List.sum,列表元素类型必须支持 +
运算符并具有零值。 所有内置算术类型都满足这些条件。 若要使用 List.average,元素类型必须支持除法(不包括整型类型,但允许浮点类型)。
List.sumBy 和 List.averageBy 函数采用函数作为参数,此函数的结果用于计算求和或平均值的值。
以下代码演示了如何使用List.sum
和List.sumBy
List.average
。
// Compute the sum of the first 10 integers by using List.sum.
let sum1 = List.sum [1 .. 10]
// Compute the sum of the squares of the elements of a list by using List.sumBy.
let sum2 = List.sumBy (fun elem -> elem*elem) [1 .. 10]
// Compute the average of the elements of a list by using List.average.
let avg1 = List.average [0.0; 1.0; 1.0; 2.0]
printfn "%f" avg1
输出为 1.000000
。
以下代码演示了 List.averageBy
如何使用 。
let avg2 = List.averageBy (fun elem -> float elem) [1 .. 10]
printfn "%f" avg2
输出为 5.5
。
列表和元组
包含元组的列表可由 zip 和解压缩函数作。 这些函数将两个单个值列表合并为一个元组列表,或将一个元组列表分成两个单个值列表。 最简单的 List.zip 函数采用两个单个元素列表,并生成单个元组对列表。 另一个版本 List.zip3 采用三个单个元素列表,并生成具有三个元素的元组列表。 下面的代码示例演示了如何使用 List.zip
。
let list1 = [ 1; 2; 3 ]
let list2 = [ -1; -2; -3 ]
let listZip = List.zip list1 list2
printfn "%A" listZip
输出如下所示:
[(1, -1); (2, -2); (3; -3)]
下面的代码示例演示了如何使用 List.zip3
。
let list3 = [ 0; 0; 0]
let listZip3 = List.zip3 list1 list2 list3
printfn "%A" listZip3
输出如下所示:
[(1, -1, 0); (2, -2, 0); (3, -3, 0)]
相应的解压缩版本 List.unzip 和 List.unzip3 采用元组列表并返回元组中的列表,其中第一个列表包含每个元组中第一个元素的所有元素,第二个列表包含每个元组的第二个元素等。
下面的代码示例演示了 List.unzip 的使用。
let lists = List.unzip [(1,2); (3,4)]
printfn "%A" lists
printfn "%A %A" (fst lists) (snd lists)
输出如下所示:
([1; 3], [2; 4])
[1; 3] [2; 4]
下面的代码示例演示如何使用 List.unzip3。
let listsUnzip3 = List.unzip3 [(1,2,3); (4,5,6)]
printfn "%A" listsUnzip3
输出如下所示:
([1; 4], [2; 5], [3; 6])
对列表元素进行作
F# 支持对列表元素执行各种作。 最简单的是 List.iter,可用于对列表的每个元素调用函数。 变体包括 List.iter2,它使你能够对两个列表的元素执行作 List.iteri,这类似于List.iter
将每个元素的索引作为参数传递给为每个元素调用的函数的参数,而 List.iteri2 是功能与List.iteri
功能List.iter2
的组合。 下面的代码示例演示了这些函数。
let list1 = [1; 2; 3]
let list2 = [4; 5; 6]
List.iter (fun x -> printfn "List.iter: element is %d" x) list1
List.iteri(fun i x -> printfn "List.iteri: element %d is %d" i x) list1
List.iter2 (fun x y -> printfn "List.iter2: elements are %d %d" x y) list1 list2
List.iteri2 (fun i x y ->
printfn "List.iteri2: element %d of list1 is %d element %d of list2 is %d"
i x i y)
list1 list2
输出如下所示:
List.iter: element is 1
List.iter: element is 2
List.iter: element is 3
List.iteri: element 0 is 1
List.iteri: element 1 is 2
List.iteri: element 2 is 3
List.iter2: elements are 1 4
List.iter2: elements are 2 5
List.iter2: elements are 3 6
List.iteri2: element 0 of list1 is 1; element 0 of list2 is 4
List.iteri2: element 1 of list1 is 2; element 1 of list2 is 5
List.iteri2: element 2 of list1 is 3; element 2 of list2 is 6
转换列表元素的另一个常用函数是 List.map,这使你可以将函数应用于列表的每个元素,并将所有结果放入新列表中。
List.map2 和 List.map3 是采用多个列表的变体。 还可以使用 List.mapi 和 List.mapi2,如果除元素外,还需要传递每个元素的索引。 这两者List.mapi2
List.mapi
的唯一区别在于List.mapi2
适用于两个列表。 以下示例演示 List.map。
let list1 = [1; 2; 3]
let newList = List.map (fun x -> x + 1) list1
printfn "%A" newList
输出如下所示:
[2; 3; 4]
以下示例演示如何使用 List.map2
。
let list1 = [1; 2; 3]
let list2 = [4; 5; 6]
let sumList = List.map2 (fun x y -> x + y) list1 list2
printfn "%A" sumList
输出如下所示:
[5; 7; 9]
以下示例演示如何使用 List.map3
。
let newList2 = List.map3 (fun x y z -> x + y + z) list1 list2 [2; 3; 4]
printfn "%A" newList2
输出如下所示:
[7; 10; 13]
以下示例演示如何使用 List.mapi
。
let newListAddIndex = List.mapi (fun i x -> x + i) list1
printfn "%A" newListAddIndex
输出如下所示:
[1; 3; 5]
以下示例演示如何使用 List.mapi2
。
let listAddTimesIndex = List.mapi2 (fun i x y -> (x + y) * i) list1 list2
printfn "%A" listAddTimesIndex
输出如下所示:
[0; 7; 18]
List.collect 类似 List.map
,只是每个元素生成一个列表,所有这些列表都串联到最终列表中。 在以下代码中,列表的每个元素生成三个数字。 这些都收集到一个列表中。
let collectList = List.collect (fun x -> [for i in 1..3 -> x * i]) list1
printfn "%A" collectList
输出如下所示:
[1; 2; 3; 2; 4; 6; 3; 6; 9]
还可以使用 List.filter,该筛选器采用布尔条件并生成一个新列表,该列表仅包含满足给定条件的元素。
let evenOnlyList = List.filter (fun x -> x % 2 = 0) [1; 2; 3; 4; 5; 6]
生成的列表为 [2; 4; 6]
.
Map 和 filter 的组合, List.choose 使你能够同时转换和选择元素。
List.choose
将一个函数应用于列表的每个元素,并在函数返回选项值 Some
时返回元素结果的新列表。
以下代码演示了如何使用 List.choose
大写单词从单词列表中选择大写单词。
let listWords = [ "and"; "Rome"; "Bob"; "apple"; "zebra" ]
let isCapitalized (string1:string) = System.Char.IsUpper string1[0]
let results = List.choose (fun elem ->
match elem with
| elem when isCapitalized elem -> Some(elem + "'s")
| _ -> None) listWords
printfn "%A" results
输出如下所示:
["Rome's"; "Bob's"]
在多个列表上运行
列表可以联接在一起。 若要将两个列表联接到一个列表,请使用 List.append。 若要联接两个以上的列表,请使用 List.concat。
let list1to10 = List.append [1; 2; 3] [4; 5; 6; 7; 8; 9; 10]
let listResult = List.concat [ [1; 2; 3]; [4; 5; 6]; [7; 8; 9] ]
List.iter (fun elem -> printf "%d " elem) list1to10
printfn ""
List.iter (fun elem -> printf "%d " elem) listResult
折叠和扫描作
某些列表作涉及所有列表元素之间的相互依赖关系。 折叠和扫描作类似于 List.iter
在每个 List.map
元素上调用函数,但这些作提供了一个名为 累加器的 附加参数,用于通过计算传递信息。
用于 List.fold
对列表执行计算。
下面的代码示例演示如何使用 List.fold 来执行各种作。
遍历列表;累加器 acc
是一个在计算继续时传递的值。 第一个参数采用累加器和 list 元素,并返回该列表元素的计算的临时结果。 第二个参数是累加器的初始值。
let sumList list = List.fold (fun acc elem -> acc + elem) 0 list
printfn "Sum of the elements of list %A is %d." [ 1 .. 3 ] (sumList [ 1 .. 3 ])
// The following example computes the average of a list.
let averageList list = (List.fold (fun acc elem -> acc + float elem) 0.0 list / float list.Length)
// The following example computes the standard deviation of a list.
// The standard deviation is computed by taking the square root of the
// sum of the variances, which are the differences between each value
// and the average.
let stdDevList list =
let avg = averageList list
sqrt (List.fold (fun acc elem -> acc + (float elem - avg) ** 2.0 ) 0.0 list / float list.Length)
let testList listTest =
printfn "List %A average: %f stddev: %f" listTest (averageList listTest) (stdDevList listTest)
testList [1; 1; 1]
testList [1; 2; 1]
testList [1; 2; 3]
// List.fold is the same as to List.iter when the accumulator is not used.
let printList list = List.fold (fun acc elem -> printfn "%A" elem) () list
printList [0.0; 1.0; 2.5; 5.1 ]
// The following example uses List.fold to reverse a list.
// The accumulator starts out as the empty list, and the function uses the cons operator
// to add each successive element to the head of the accumulator list, resulting in a
// reversed form of the list.
let reverseList list = List.fold (fun acc elem -> elem::acc) [] list
printfn "%A" (reverseList [1 .. 10])
函数名称中具有数字的这些函数的版本对多个列表进行作。 例如, List.fold2 对两个列表执行计算。
下面的示例演示了如何使用 List.fold2
。
// Use List.fold2 to perform computations over two lists (of equal size) at the same time.
// Example: Sum the greater element at each list position.
let sumGreatest list1 list2 = List.fold2 (fun acc elem1 elem2 ->
acc + max elem1 elem2) 0 list1 list2
let sum = sumGreatest [1; 2; 3] [3; 2; 1]
printfn "The sum of the greater of each pair of elements in the two lists is %d." sum
List.fold
和 List.scan 在返回额外参数的最终值时 List.fold
有所不同,但 List.scan
返回额外参数的中间值列表(以及最终值)。
其中每个函数都包含一个反向变体,例如 List.foldBack,它因列表遍历的顺序和参数的顺序而异。 此外, List.fold
还有 List.foldBack
一些变体 List.fold2 和 List.foldBack2,它们采用两个相同长度的列表。 在每个元素上执行的函数可以使用这两个列表的相应元素来执行某些作。 两个列表的元素类型可能有所不同,如以下示例所示,其中一个列表包含银行账户的交易金额,另一个列表包含交易类型:存款或取款。
// Discriminated union type that encodes the transaction type.
type Transaction =
| Deposit
| Withdrawal
let transactionTypes = [Deposit; Deposit; Withdrawal]
let transactionAmounts = [100.00; 1000.00; 95.00 ]
let initialBalance = 200.00
// Use fold2 to perform a calculation on the list to update the account balance.
let endingBalance = List.fold2 (fun acc elem1 elem2 ->
match elem1 with
| Deposit -> acc + elem2
| Withdrawal -> acc - elem2)
initialBalance
transactionTypes
transactionAmounts
printfn "%f" endingBalance
对于求和等计算,并List.foldBack
具有相同的效果,List.fold
因为结果不依赖于遍历顺序。 在以下示例中, List.foldBack
用于在列表中添加元素。
let sumListBack list = List.foldBack (fun elem acc -> acc + elem) list 0
printfn "%d" (sumListBack [1; 2; 3])
// For a calculation in which the order of traversal is important, fold and foldBack have different
// results. For example, replacing fold with foldBack in the listReverse function
// produces a function that copies the list, rather than reversing it.
let copyList list = List.foldBack (fun elem acc -> elem::acc) list []
printfn "%A" (copyList [1 .. 10])
以下示例返回到银行帐户示例。 这一次添加了新的事务类型:利息计算。 结束余额现在取决于事务的顺序。
type Transaction2 =
| Deposit
| Withdrawal
| Interest
let transactionTypes2 = [Deposit; Deposit; Withdrawal; Interest]
let transactionAmounts2 = [100.00; 1000.00; 95.00; 0.05 / 12.0 ]
let initialBalance2 = 200.00
// Because fold2 processes the lists by starting at the head element,
// the interest is calculated last, on the balance of 1205.00.
let endingBalance2 = List.fold2 (fun acc elem1 elem2 ->
match elem1 with
| Deposit -> acc + elem2
| Withdrawal -> acc - elem2
| Interest -> acc * (1.0 + elem2))
initialBalance2
transactionTypes2
transactionAmounts2
printfn "%f" endingBalance2
// Because foldBack2 processes the lists by starting at end of the list,
// the interest is calculated first, on the balance of only 200.00.
let endingBalance3 = List.foldBack2 (fun elem1 elem2 acc ->
match elem1 with
| Deposit -> acc + elem2
| Withdrawal -> acc - elem2
| Interest -> acc * (1.0 + elem2))
transactionTypes2
transactionAmounts2
initialBalance2
printfn "%f" endingBalance3
Function List.reduce 有点类似List.fold
List.scan
,但除了不传递单独的累加器外,List.reduce
还采用一个函数,该函数采用元素类型的两个参数而不是只采用一个参数,其中一个参数充当累加器,这意味着它存储计算的中间结果。
List.reduce
首先对前两个列表元素进行作,然后使用作的结果以及下一个元素。 由于没有单独的累加器具有其自己的类型, List.reduce
因此只能在累加器与元素类型具有相同的类型时使用 List.fold
。 以下代码演示了如何使用 List.reduce
。
List.reduce
如果提供的列表没有元素,则引发异常。
在以下代码中,对 lambda 表达式的第一次调用给定参数 2 和 4,并返回 6,下一次调用为参数 6 和 10,因此结果为 16。
let sumAList list =
try
List.reduce (fun acc elem -> acc + elem) list
with
| :? System.ArgumentException as exc -> 0
let resultSum = sumAList [2; 4; 10]
printfn "%d " resultSum
在列表和其他集合类型之间进行转换
该 List
模块提供用于转换序列和数组的函数。 若要转换为序列或从序列转换,请使用 List.toSeq 或 List.ofSeq。 若要转换为数组或从数组转换,请使用 List.toArray 或 List.ofArray。
其他作
有关列表的其他作的信息,请参阅库参考主题 列表模块。