共用方式為


列表 / 清單

F# 中的清單是相同類型的已排序、不可變的元素系列。 若要在清單上執行基本作業,請使用 List 模組中的函式。

建立和初始化清單

您可以藉由明確列出元素來定義清單,並以分號分隔並以方括弧括住,如下列程式代碼行所示。

let list123 = [ 1; 2; 3 ]

您也可以在元素之間放置換行符,在此情況下,分號是選擇性的。 當元素初始化表達式較長,或您想要包含每個專案的批注時,後者的語法可能會導致更容易閱讀的程序代碼。

let list123 = [ 1; 2; 3 ]

一般而言,所有清單項目都必須是相同的類型。 例外狀況是,將專案指定為基底型別的清單可以有衍生型別的專案。 因此,可以接受下列專案,因為 ButtonCheckBox 都衍生自 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) 運算子將元素附加至清單 :: 。 如果 list1[2; 3; 4],下列程式代碼會 list2 建立為 [100; 2; 3; 4]

let list2 = 100 :: list1

您可以使用 運算符串連具有相容類型的 @ 清單,如下列程式代碼所示。 如果 list1[2; 3; 4]list2[100; 2; 3; 4],則此程式代碼會 list3 建立為 [2; 3; 4; 100; 2; 3; 4]

let list3 = list1 @ list2

清單模組中提供執行清單作業的函式。

因為 F# 中的清單是不可變的,所以任何修改作業都會產生新的清單,而不是修改現有的清單。

F# 中的清單會實作為單向連結清單,這表示只存取清單前端的作業為 O(1),而元素存取則是 O(n)。

屬性

清單類型支援下列屬性:

房產 類型 說明
前端 '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 元素是最快速且最容易存取的專案。 使用 Property Head 或 module 函式 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.sortList.sortByList.sortWith 函式排序列表。 排序函式會決定要使用這三個函式中的哪一個。 List.sort 會使用預設的泛型比較。 泛型比較會根據泛型比較函式使用全域運算符來比較值。 它可有效率地搭配各種不同的專案類型運作,例如簡單的數值類型、Tuple、記錄、歧視等位、清單、陣列,以及任何實作 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)的選項值。 傳回結果, 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 式會傳回清單的第一個元素,如果這類專案存在,則會傳回滿足條件,但如果沒有的話,則傳回選項值 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.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

清單和 Tuple

包含 Tuple 的清單可由 zip 和 unzip 函式作。 這些函式會將兩份單一值清單合併成一個 Tuple 清單,或將一份 Tuple 列表分成兩個單一值清單。 最簡單的List.zip函 會採用兩份單一元素清單,併產生單一 Tuple 配對清單。 另一個版本 List.zip3 會採用三份單一元素清單,併產生具有三個元素的單一 Tuple 清單。 下列程式代碼範例示範 如何使用 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 會擷取 Tuple 清單,並在 Tuple 中傳回清單,其中第一個清單包含每個 Tuple 中第一個元素的所有元素,而第二個清單則包含每個 Tuple 的第二個專案等等。

下列程式代碼範例示範 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.map2List.map3 是採用多個列表的變化。 您也可以使用 List.mapiList.mapi2,如果除了 元素之外,函式還需要傳遞每個專案的索引。 和 List.mapi 之間的List.mapi2唯一差異在於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.iterList.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.foldList.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.foldList.scan,不同之處在於,與其傳遞個別累加器,List.reduce而是採用元素類型的兩個自變數,而不是只採用一個自變數的函式,而其中一個自變數會作為累加器,這表示它會儲存計算的中繼結果。 List.reduce 會先在前兩個清單元素上作,然後使用作業的結果以及下一個專案。 因為沒有個別的累積器有自己的類型,因此只有在累加器和元素類型具有相同類型時, List.reduce 才能取代 List.fold 。 下列程式代碼示範 如何使用 List.reduceList.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.toSeqList.ofSeq。 若要轉換至陣列或從數位轉換,請使用 List.toArrayList.ofArray

其他作業

如需清單上其他作業的詳細資訊,請參閱連結庫參考主題 清單模組

另請參閱