清單

在 F# 中,list 是包含一系列經過排序且類型相同的固定元素。 若要執行清單的基本運算,請使用 List 模組中的函式。

建立及初始化 list

您可以藉由明確列出元素 (以逗號分隔並括以方括號) 來定義 list,如下列程式碼所示。

let list123 = [ 1; 2; 3 ]

您也可以在元素之間加入分行符號;若您選擇加入分行符號,就不一定需要使用分號。 當元素初始化運算式比較長,或當您想要為每個元素加入逗號時,以後一種語法編寫的程式碼會比較容易閱讀。

let list123 = [ 1; 2; 3 ]

通常 list 的所有元素都應必須是同一類型。 但當 list 指定的元素具有衍生類型的基底類型時,就不在此限。 下列的 ButtonCheckBox 因為都是從 Control 衍生而來,所以可接受。

let myControlList: Control list = [ new Button(); new CheckBox() ]

如下列程式碼所示,您也可以使用以整數指定的範圍 (以範圍運算子 .. 分隔) 來定義 list 元素。

let list1 = [ 1..10 ]

空 list 由不含任何內容的一對方括號指定。

// An empty list.
let listEmpty = []

您也可以使用順序運算式建立 list。 如需詳細資訊,請參閱序列運算式。 例如下列程式碼會建立從 1 到 10 之整數平方的 list。

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

使用 list 的運算子

您可以使用 :: (cons) 運算子。 若 list1[2; 3; 4],下列程式碼將 list2 建立為 [100; 2; 3; 4]

let list2 = 100 :: list1

您可以使用 @ 運算子串流具有相容類型的 list,如下列程式碼所示。 當 list1[2; 3; 4]list2[100; 2; 3; 4] 時,此程式碼會將 list3 建立為 [2; 3; 4; 100; 2; 3; 4]

let list3 = list1 @ list2

List 模組提供可用於執行清單運算的函式。

由於 F# 中的 list 為固定,因此任何修改作業都會產生新的 list,而不會修改現有的 list。

F# 中的清單以單向連結清單形式實作,亦即只存取清單標頭的運算為 O(1),而存取元素的運算為 O(n)。

屬性

list 類型支援下列屬性:

屬性 類型​ 描述
Head 'T 第一個元素。
Empty 'T list 此為靜態屬性,會傳回適當類型的空 list。
IsEmpty bool true 表示 list 不含任何元素。
項目 'T 使用位於指定索引的元素 (以零為基底)。
長度 int 項目的數目。
Tail 'T list 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))

使用 list

使用 list 編寫程式讓您只需要編寫小量的程式碼,就可以執行複雜的運算。 本節說明一些使用函式編寫程式時不可或缺的常用 list 運算。

list 的遞迴功能

list 是唯一適合遞迴程式設計技巧的函式。 假設有一項作業必須對 list 的每個元素執行。 您可以利用遞迴方式執行此作業,方法是先對 list 的 head 執行運算,再傳遞 list 的 tail (此 list 只含原始 list,而不含第一個元素,所以比較小),然後再執行下一個遞迴層級的程式碼。

若要編寫這類遞迴函式,可以在模式比對中使用 cons 運算子 (::),以區分 list 的 head 與 tail。

下列程式碼範例示範如何使用模式比對,實作執行 list 運算的遞迴函式。

let rec sum list =
    match list with
    | head :: tail -> head + sum tail
    | [] -> 0

前述程式碼對於小型 list 的效果很好,但對於大型的 list,可能會發生堆疊溢位。 下列程式碼是前述程式碼的改良版,運用了遞迴函式標準技巧中的 accumulator 引數。 使用 accumulator 引數可以遞迴函式的 tail,進而達到節省空間的目的。

let sum list =
    let rec loop list acc =
        match list with
        | head :: tail -> loop tail (acc + head)
        | [] -> acc

    loop list 0

函式 RemoveAllMultiples 為遞迴函式,可接受兩個 list。 第一個 list 包含倍數要移除的數字;第二個 list 是數字要移除的 list。 下列範例會使用此遞迴函式消除 list 中的所有非質數,而只保留質數。

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 會周遊 list。 因此為 O(n)。 若您的程式碼需要頻繁地使用 List.nth,您或可改用 array,而不要使用 list。 array 中的元素存取為 O(1)。

List 的布林運算

List.isEmpty 函式可確認清單有無任何元素。

List.exists 函式會對清單的元素套用布林值測試;如有任何元素通過測試,即傳回 trueList.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 的排序運算

List.sortList.sortByList.sortWith 函式皆可排序清單。 排序函式可指定要使用這三個函式中的哪一個函式。 List.sort 會使用預設的泛型比較。 泛型比較會依不同的泛型比較函式而使用不同的全域運算子來比較值。 其可與多種元素類型搭配使用,例如簡單的數值類型、tuple、記錄、差別聯集、list、array 及所有實作 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 的搜尋運算

list 支援多種搜尋運算。 List.find 最簡單,可讓您尋找第一個符合指定條件的元素。

下列程式碼範例示範如何使用 List.find 從 list 中尋找第一個可以被 5 整除的數字。

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

The result is 5.

若元素必須先經過轉換,可呼叫 List.pick,使其取用傳回選項的函式,然後尋找第一個選項值為 Some(x) 的函式。 List.pick 不會傳回元素,而會傳回結果 x。 若找不到相符的元素,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 函式會傳回 list 中第一個滿足條件的元素 (如其存在);若找不到,即會傳回選項值 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.

List 的算術運算

List 模組內建常用的算術運算,例如加總與平均。 若要使用 List.sum,清單元素類型必須支援 + 運算子,且值必須等於零。 所有內建算術類型皆滿足這些條件。 若要使用 List.average,元素類型必須支援整除,且排除整數類型,但包含浮點類型。 List.sumByList.averageBy 函式可將函式用作參數,並使用該函式的結果計算加總或平均的值。

下列程式碼示範 List.sumList.sumByList.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

List 與 Tuple

zip 及 unzip 函式可以操作包含 tuple 的 list。 這些函式會將各自包含一個值的兩個 list 合併成一份元組清單,或將一份元組清單分割成兩個只含單一值的 list。 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.unzipList.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])

List 元素的運算

F# 支援多種 list 元素運算。 最簡單的 List.iter 可讓您對清單中的每個元素呼叫函式。 變化型包括:List.iter2,可讓您對兩個清單中的元素執行運算;List.iteriList.iter 類似,唯一不同點是前者會將每個元素的索引,以引數形式傳遞給為每個元素所呼叫的函式;List.iteri2 兼具 List.iter2List.iteri 的功能。 下列程式碼範例會示範這些函數。

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.map2List.map3 為變化型,可使用多個清單。 除了元素之外,若需要傳遞每個元素的索引給函式,也可使用 List.mapiList.mapi2List.mapi2List.mapi 的唯一差別在於 List.mapi2 可與兩個 list 搭配使用。 下列範例示範 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.collectList.map 類似,唯一差別在於每個元素會產生一個清單,而所有產生的清單會串連成最終清單。 在下列程式碼中,list 的每個元素都會產生三個數字。 所有數字都會收集到一個 list 中。

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]

所得 list 為 [2; 4; 6]

List.choose 結合了對應與篩選功能,可讓您同時轉換及選取元素。 List.choose 會套用可以傳回選項給每個 list 元素的函式,並會在函式傳回選項值 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 的運算

多個 list 可以相互結合。 若要將兩個清單合而為一,可使用 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

Fold 與 Scan 運算

有些 list 運算涉及所有 list 元素間彼此的相依性。 摺疊與掃描運算與 List.iterList.map 類似,您可以對每個元素較用一個函式,但這些運算會另外提供一個稱為「累加器」的參數,可運載整個運算期間的資訊。

使用 List.fold 對 list 執行運算。

下列程式碼範例示範如何使用 List.fold 執行各種運算。

清單會經過周遊;accumulator acc 一值會隨著運算進行而傳遞。 第一個引數在接受 accumulator 及 list 元素之後,會傳回 list 元素的暫時結果。 第二個引數是 accumulator 的初始值。

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 執行,函式名稱中會有一位數字記錄其版本。 例如,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.foldList.scan 的差別在於,List.fold 會傳回額外參數的最終值,而 List.scan 會傳回額外參數的中繼值清單 (與最終值)。

這些函式各有一個反向的變化型。例如 List.foldBack 周遊清單的順序會不同,引數順序也會不同。 此外,List.foldList.foldBack 也有變化型 List.fold2List.foldBack2,皆接受兩個等長的清單。 對每個元素執行的函式,皆可使用兩個 list 的對應元素執行特定動作。 如下列範例所示,兩個 list 的元素類型可以不同,其中一個 list 包含銀行帳戶的異動金額,另一個 list 則包含異動的類型 (存款或提款)。

// 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.foldList.foldBack 的結果與周遊順序無關,所以兩者的效果相同。 在下列範例中,List.foldBack 會用於新增 list 中的元素。

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

函式 List.reduceList.foldList.scan 有些許類似,但 List.reduce 不會四處傳遞個別的累加器,而會使用可以接受兩個 (而非只有一個) 元素類型引數的函式,並以其中一個引數作為累加器,亦即會儲存運算的中繼結果。 List.reduce 會從運算頭兩個 list 元素開始,然後再並用運算結果與下一個元素。 因為沒有任何具有專屬類型的 accumulator,所以可以使用 List.reduce 取代 List.fold,但前提是 accumulator 與元素類型必須屬於相同類型。 下列程式碼示範 List.reduce 的用法。 若提供的 list 不含任何元素,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 模組提供可以讓 sequence 與 array 相互轉換的函式。 若要轉換成序列或復原,請使用 List.toSeqList.ofSeq。 若要轉換成陣列或復原,請使用 List.toArrayList.ofArray

其他運算

如需其他清單運算的資訊,請參閱程式庫參考主題 List Module

另請參閱