Seznamy (F#)
Seznam v jazyce F # je uspořádaný, nezměnitelné řadu prvků stejného typu.Provádět základní operace s seznamů pomocí funkcí v seznam modulu.
Vytváření a inicializuje se zobrazí seznam
Seznam můžete definovat uvedením explicitně prvky, oddělené středníky a uzavřeny do hranatých závorek, jak je znázorněno v následujícím řádku kódu.
let list123 = [ 1; 2; 3 ]
Můžete také umístit zalomení mezi elementy, v takovém případě jsou volitelné středníky.Druhém syntaxe může vést k čitelnější kódu, když jsou výrazy elementu inicializace delší, nebo když chcete zahrnout komentáře pro každý prvek.
let list123 = [
1
2
3 ]
Všechny elementy seznamu za normálních okolností musí být stejného typu.Výjimka je, že seznam, ve kterém jsou zadány elementy, chcete-li být základní typ může obsahovat elementy, které jsou odvozené typy.Následující je tedy přijatelné, protože oba Button a CheckBox být odvozen od třídy Control.
let myControlList : Control list = [ new Button(); new CheckBox() ]
Prvky seznamu můžete také definovat pomocí rozsah indikovaný celá čísla oddělená operátoru range (..), jak je znázorněno v následujícím kódu.
let list1 = [ 1 .. 10 ]
Seznam můžete také definovat pomocí konstrukci cyklu, jako v následujícím kódu.
let listOfSquares = [ for i in 1 .. 10 -> i*i ]
Prázdný seznam je zadána jako dvojice hranaté závorky s nic mezi nimi.
// An empty list.
let listEmpty = []
Výraz sekvence lze také použít k vytvoření seznamu.V zobrazení "Sekvenci výrazů" sekvence.Například následující kód vytvoří seznam čtverce celá čísla od 1 do 10.
let squaresList = [ for i in 1 .. 10 -> i * i ]
Operátory pro práci s seznamy
Elementy do seznamu můžete připojit pomocí :: operátor (nevýhody).Pokud list1 je [2; 3; 4], následující kód vytvoří list2 jako [100; 2; 3; 4].
let list2 = 100 :: list1
Je možné řetězit seznamy, které mají typy kompatibilní s použitím @ operátoru, jako v následujícím kódu.Pokud list1 je [2; 3; 4] a list2 je [100; 2; 3; 4 ], tento kód vytvoří list3 jako [2; 3; 4; 100; 2; 3; 4].
let list3 = list1 @ list2
Funkce pro provádění operací na seznamy jsou k dispozici v seznam modulu.
Protože se zobrazí v jazyce F # nezměnitelné, žádné změny operace generovat nové seznamy namísto upravíte existující seznamy.
Zobrazí v jazyce F # jsou implementovány jako jednotlivě propojené seznamy, což znamená, že operace, které mají přístup pouze první pozice v seznamu jsou o(1), která, ke kterému je element přístup O (n).
Vlastnosti
Typ seznamu podporuje následující vlastnosti:
Vlastnost |
Typ |
Popis |
---|---|---|
'T |
První prvek. |
|
'T list |
Statické vlastnosti, která vrací prázdný seznam příslušného typu. |
|
bool |
truePokud seznam neobsahuje žádné elementy. |
|
'T |
Element se zadaným indexem (počítáno od nuly). |
|
int |
Počet elementů. |
|
'T list |
Seznam bez prvním elementem. |
Následuje několik příkladů použití těchto vlastností.
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))
Použití seznamů
Programování s seznamy umožňuje provádět složité operace s malou část kódu.Tato část popisuje běžné operace na seznamy, které jsou důležité pro funkční programování.
Rekurze se seznamy
Seznamy jsou jedinečně hodí pro rekurzivní techniky programování.Zvažte operaci, která musí být provedeny na každý prvek seznamu.Můžete provést tento rekurzivně provozující head seznamu a poté předáním funkce tail ze seznamu, který je menší seznam, který se skládá ze seznamu původní bez první prvek, potom znovu na novou úroveň rekurze.
K zápisu rekurzivní funkce, použijte operátor nevýhody (::) v porovnávání, která umožňuje oddělení vedoucí seznam zadní.
Následující příklad kódu ukazuje, jak používat shody pomocí sekvencí k implementaci rekurzivní funkce, která provádí operace v seznamu.
let rec sum list =
match list with
| head :: tail -> head + sum tail
| [] -> 0
Předchozí kód je dobře použitelný pro malé seznamů, ale pro větší seznamy ji může přetečení zásobníku.Následující kód vylepšuje do tohoto kódu s použitím argumentu akumulátorová standardní techniky pro práci s rekurzivní funkce.Použití argumentu akumulátorová usnadňuje rekurzivní funkce tail funkce, které jsou uloženy prostor v zásobníku.
let sum list =
let rec loop list acc =
match list with
| head :: tail -> loop tail (acc + head)
| [] -> acc
loop list 0
Funkce RemoveAllMultiples je rekurzivní funkce, která přebírá dva seznamy.První seznam obsahuje čísla, jejichž násobky budou odebrány a druhý seznam je seznam, ze které chcete odebrat čísla.Kód v následujícím příkladu používá tuto funkci rekurzivní k odstranění všech bez primárního čísel ze seznamu, ponechejte seznam čísel primárního jako výsledek.
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)
Výstup je následující:
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]
Modul funkce
Seznam modulu poskytuje funkce, které přistupují k prvků seznamu.Head element je nejrychlejší a nejjednodušší pro přístup.Použijte vlastnost Head nebo funkci modulu List.head.Funkce tail seznamu může přistupovat pomocí funkce Tail vlastnost nebo List.tail funkce.Chcete-li vyhledat elementu podle indexu, použijte List.nth funkce.List.nthpřekračují seznamu.Proto je O (n).Pokud váš kód využívá List.nth často, můžete chtít zvažte použití pole místo seznamu.O(1), která je element přístup v polích.
Logická operace seznamy
List.isEmpty funkce určuje, zda seznam obsahuje všechny prvky.
List.exists funkce se vztahuje na logickou hodnotu test pro prvky seznam a vrátí hodnotu true Pokud libovolný element splňuje test.List.exists2 je podobný, ale po sobě jdoucích dvojice elementů ve dvou seznamech bude pracovat.
Následující kód ukazuje použití 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)
Výstup je následující:
For list [0; 1; 2; 3], contains zero is true
Následující příklad ukazuje použití 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
Výstup je následující:
Lists [1; 2; 3; 4; 5] and [5; 4; 3; 2; 1] have at least one equal element at the same position.
Můžete použít List.forall Pokud chcete testovat, zda všechny prvky v seznamu splňují podmínku.
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])
Výstup je následující:
true
false
Podobně List.forall2 Určuje, zda všechny elementy v odpovídající pozice ve dvou seznamech vyhovět logický výraz, který zahrnuje každý pár elementů.
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])
Výstup je následující:
true
false
Operace řazení na seznamy
List.sort, List.sortBy, a List.sortWith funkce seřadit seznamy.Funkce třídění určuje, které z těchto tří funkcí používat.List.sortpoužívá výchozí obecný porovnání.Obecný porovnání použije globální operátory na základě funkce obecný porovnání k porovnání hodnoty.Efektivní funguje s širokou škálu typy elementů, například jednoduché číselné typy, řazených kolekcí členů, záznamy, rozlišovaná sjednocení, seznamů, polí a žádný typ, který implementuje IComparable.Pro typy, které implementují IComparable, používá obecný porovnání CompareTo funkce.Obecný porovnání také funguje s řetězci, ale používá pořadí řazení jazykově nezávislé.Obecný porovnání nesmí být použita v nepodporované typy, jako jsou typy funkce.Také výkon výchozí obecný porovnání je nejvhodnější pro malé strukturovaného typů; pro větší strukturovaného typy, které je třeba ve srovnání a seřadit často, zvažte implementaci IComparable a poskytnutí efektivní provádění CompareTo metody.
List.sortBypoužívá funkci, která vrátí hodnotu, která se používá jako kritéria řazení a List.sortWith přijímá jako argument funkce porovnání.Tyto druhém dvě funkce jsou užitečné při práci s typy, které nepodporují porovnání, nebo pokud porovnání vyžaduje složitější sémantiku porovnání, stejně jako v případě podporující jazykové verze řetězce.
Následující příklad ukazuje použití List.sort.
let sortedList1 = List.sort [1; 4; 8; -2; 5]
printfn "%A" sortedList1
Výstup je následující:
[-2; 1; 4; 5; 8]
Následující příklad ukazuje použití List.sortBy.
let sortedList2 = List.sortBy (fun elem -> abs elem) [1; 4; 8; -2; 5]
printfn "%A" sortedList2
Výstup je následující:
[1; -2; 4; 5; 8]
Další příklad ukazuje použití List.sortWith.V tomto příkladu je funkce vlastní porovnání compareWidgets se používá k porovnání nejprve jedno pole vlastního typu, a potom jiný when jsou stejné hodnoty první pole.
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
Výstup je následující:
[{ID = 92;
Rev = 1;}; {ID = 92;
Rev = 1;}; {ID = 100;
Rev = 2;}; {ID = 100;
Rev = 5;}; {ID = 110;
Rev = 1;}]
Operace hledání v seznamy
Mnoho operace vyhledávání jsou podporovány pro seznamy.Nejjednodušší, List.find, umožňuje vyhledat první prvek, který odpovídá dané podmínce.
Následující příklad kódu ukazuje použití List.find najít první číslo, které je dělitelná 5 v seznamu.
let isDivisibleBy number elem = elem % number = 0
let result = List.find (isDivisibleBy 5) [ 1 .. 100 ]
printfn "%d " result
Výsledkem je 5.
Elementy musí být nejprve ošetřeny, kontaktujte List.pick, který přebírá funkce, vrátí možnost a hledá první možnost Hodnota, která je Some(x).Namísto elementu, který vrací List.pick vrátí výsledek x.Pokud není nalezen žádný odpovídající prvek, List.pick vyvolá KeyNotFoundException.Následující kód ukazuje použití 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
Výstup je následující:
"b"
Jiná skupina operací vyhledávání List.tryFind a související funkce vrátit hodnotu možnosti.List.tryFind Funkce vrací první prvek seznamu, který splňuje podmínku, pokud takový prvek existuje, ale hodnotu možnosti None není-li.Změna List.tryFindIndex vrátí index elementu, pokud je nějaká nalezena, nikoli elementu samotného.Tyto funkce jsou uvedeny v následující kód.
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."
Výstup je následující:
The first even value is 22.
The first even value is at position 8.
Aritmetické operace s seznamy
Běžné aritmetické operace, například součet a průměr jsou integrovány do seznam modulu.Budete chtít pracovat s List.sum, musí podporovat typ elementu seznamu + operátor a nemají žádnou hodnotu.Všechny vestavěné typy aritmetických splňovat tyto podmínky.Budete chtít pracovat s List.average, typ elementu musí podporovat dělení bez zbytek, který vyloučí integrální typy, ale umožňuje pro plovoucí bod typy.List.sumBy a List.averageBy funkce přebírat funkci jako parametr a výsledky této funkce se používají k výpočtu hodnoty pro součet nebo průměr.
Následující kód ukazuje použití List.sum, List.sumBy, a 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
Výstupem je 1.000000.
Následující kód ukazuje použití List.averageBy.
let avg2 = List.averageBy (fun elem -> float elem) [1 .. 10]
printfn "%f" avg2
Výstupem je 5.5.
Seznamy a řazených kolekcí členů
Seznamy, které obsahují řazených kolekcí členů smí uživatel manipulovat zip a rozbalení funkce.Tyto funkce sloučit dva seznamy jedné hodnot do jednoho seznamu řazené kolekce členů nebo rozdělit jeden seznam řazených kolekcí členů do dvou seznamů jedné hodnoty.Nejjednodušší List.zip funkce přebírá dva seznamy jednotlivé prvky a vytváří jeden seznam párů řazené kolekce členů.Jinou verzi, List.zip3, přebírá tři seznamy jednotlivé prvky a vytváří jeden seznam řazených kolekcí členů, které mají tři prvky.Následující příklad kódu ukazuje použití List.zip.
let list1 = [ 1; 2; 3 ]
let list2 = [ -1; -2; -3 ]
let listZip = List.zip list1 list2
printfn "%A" listZip
Výstup je následující:
[(1, -1); (2, -2); (3; -3)]
Následující příklad kódu ukazuje použití List.zip3.
let list3 = [ 0; 0; 0]
let listZip3 = List.zip3 list1 list2 list3
printfn "%A" listZip3
Výstup je následující:
[(1, -1, 0); (2, -2, 0); (3, -3, 0)]
Odpovídající rozbalení verze, List.unzip a List.unzip3, provést vrácení seznamy a seznamy řazené kolekce členů v řazené kolekce členů, kde první seznam obsahuje všechny prvky, které byly v každé řazené kolekce členů první a druhý seznam obsahuje druhého prvku každý řazené kolekce členů, a tak dále.
Následující příklad kódu ukazuje použití List.unzip.
let lists = List.unzip [(1,2); (3,4)]
printfn "%A" lists
printfn "%A %A" (fst lists) (snd lists)
Výstup je následující:
([1; 3], [2; 4])
[1; 3] [2; 4]
Následující příklad kódu ukazuje použití List.unzip3.
let listsUnzip3 = List.unzip3 [(1,2,3); (4,5,6)]
printfn "%A" listsUnzip3
Výstup je následující:
([1; 4], [2; 5], [3; 6])
Operace s prvky seznamu
F # podporuje různé operace v seznamu elementů.Nejjednodušší je List.iter, která umožňuje volání funkce na každý prvek seznamu.Zahrnout variace List.iter2, umožňující provádění operací na elementy dva seznamy, List.iteri, což je stejná jako List.iter s tím rozdílem, že index každý prvek je předán jako argument funkce, která je volána pro každý prvek a List.iteri2, který je kombinací funkci List.iter2 a List.iteri.Následující příklad kódu ukazuje tyto funkce.
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
Výstup je následující:
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
Jiné často používané funkce, která transformuje prvky seznamu je List.map, který můžete použít funkci pro každý prvek seznam a všechny výsledky do nového seznamu.List.map2 a List.map3 jsou varianty, které berou více seznamů.Můžete také použít List.mapi a List.mapi2, je-li kromě elementu, funkce musí být předána index každého prvku.Jediným rozdílem mezi List.mapi2 a List.mapi je, že List.mapi2 pracuje se dvěma seznamy.Následující příklad ukazuje List.map.
let list1 = [1; 2; 3]
let newList = List.map (fun x -> x + 1) list1
printfn "%A" newList
Výstup je následující:
[2; 3; 4]
Následující příklad ukazuje použití 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
Výstup je následující:
[5; 7; 9]
Následující příklad ukazuje použití List.map3.
let newList2 = List.map3 (fun x y z -> x + y + z) list1 list2 [2; 3; 4]
printfn "%A" newList2
Výstup je následující:
[7; 10; 13]
Následující příklad ukazuje použití List.mapi.
let newListAddIndex = List.mapi (fun i x -> x + i) list1
printfn "%A" newListAddIndex
Výstup je následující:
[1; 3; 5]
Následující příklad ukazuje použití List.mapi2.
let listAddTimesIndex = List.mapi2 (fun i x y -> (x + y) * i) list1 list2
printfn "%A" listAddTimesIndex
Výstup je následující:
[0; 7; 18]
List.Collect je stejná jako List.map, s tím rozdílem, že každý prvek vytváří seznam a všechny tyto seznamy jsou zřetězených do konečného seznamu.V následujícím kódu generuje každý prvek seznamu tři čísla.Všechny jsou shromažďovány do jednoho seznamu.
let collectList = List.collect (fun x -> [for i in 1..3 -> x * i]) list1
printfn "%A" collectList
Výstup je následující:
[1; 2; 3; 2; 4; 6; 3; 6; 9]
Můžete také použít List.filter, který přebírá logické podmínky a vytváří nový seznam, který se skládá pouze z elementů, které odpovídají dané podmínce.
let evenOnlyList = List.filter (fun x -> x % 2 = 0) [1; 2; 3; 4; 5; 6]
V rozevíracím seznamu je [2; 4; 6].
Kombinace mapy a filtr List.choose vám umožňuje transformovat a vybrat elementy současně.List.choosepoužije funkci, která vrátí možnost pro každý prvek seznam a vrátí hodnotu nový seznam výsledků pro elementy, pokud funkce vrací hodnotu možnosti Some.
Následující kód ukazuje použití List.choose k výběru převedených na velká písmena slova mimo seznam slov.
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
Výstup je následující:
["Rome's"; "Bob's"]
Operace s více seznamů
Seznamy můžete spojit dohromady.Chcete-li spojit dva seznamy do jedné, použijte List.append.Chcete-li připojit se k více než dva seznamy, použijte 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
Skládání a prohledávání
Některé operace seznamu zahrnovat vzájemné závislosti mezi všechny elementy seznamu.Operace skládání a prohledávání jsou jako List.iter a List.map v tom volání funkce pro každý element, ale tyto operace poskytnout další parametr s názvem akumulátorová který přenáší informace prostřednictvím výpočtu.
Použití List.fold k provedení výpočtu v seznamu.
Následující příklad kódu ukazuje použití List.fold k provádění různých operací.
Je seznam vyčerpán; je zásobník acc je hodnota, která je předána podél během výpočtu.První argument přijímá je zásobník a element seznamu a vrací pomocný výsledek výpočtu pro daný prvek seznamu.Druhý argument je počáteční hodnota je zásobník.
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])
Verze z těchto funkcí, které mají číslici v názvu funkce provádět operace s více než jeden seznam.Můžete například List.fold2 provádí výpočty dva seznamy.
Následující příklad ukazuje použití 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.folda List.scan se liší v tomto List.fold vrátí konečná hodnota parametru navíc, ale List.scan vrátí seznam pomocných hodnot (spolu s konečná hodnota) navíc parametru.
Každá z těchto funkcí zahrnuje reverzní variantou, například List.foldBack, která se liší v pořadí, ve které je seznam vyčerpán a pořadí argumentů.Také List.fold a List.foldBack mají varianty, List.fold2 a List.foldBack2, které přijímají dva seznamy stejné délky.Funkce, která spustí pro každý element slouží k provedení určité akce odpovídající elementy oba seznamy.Typy elementů z těchto seznamů se může lišit, jako v následujícím příkladu, ve kterém jeden seznam obsahuje objemy transakce pro účet banky a dalších seznam obsahuje typ transakce: uložení nebo zrušení.
// 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
Pro výpočet jako souhrn List.fold a List.foldBack mají stejný účinek, protože výsledek není pořadí přechod zálohovaných závislá.V následujícím příkladu List.foldBack se používá k přidání elementů v seznamu.
let sumListBack list = List.foldBack (fun acc elem -> 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])
Následující příklad vrátí v příkladu bank účtu.Tento čas je přidán nový typ transakce: výpočtu zájem.Konečný zůstatek nyní závisí pořadí transakce.
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
Funkce List.reduce je něco jako List.fold a List.scan, s tím rozdílem, že namísto předávání kolem samostatné akumulátoru, List.reduce provede funkci, která přebírá dva argumenty elementu zadejte namísto pouze jeden, a jeden z těchto argumentů funguje jako je zásobník, což znamená, že ukládá mezilehlá výsledek výpočtu.List.reduceSpustí používáním na prvních dvou seznam prvků a potom použije výsledek operace spolu se na další element.Vzhledem k tomu, že není k dispozici samostatné akumulátor, který má svůj vlastní typ List.reduce lze použít místo List.fold pouze pokud je zásobník a typ elementu mít stejného typu.Následující kód ukazuje použití List.reduce.List.reducevyvolá výjimku, pokud seznamu podle neobsahuje žádné elementy.
V následujícím kódu první volání výrazu lambda je zadána argumenty 2 a 4 a vrátí 6 a další volání je zadána argumenty 6 a 10, takže výsledek je 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
Převod mezi seznamy a dalších typů kolekce
List Modul poskytuje funkce pro převod do a z sekvence a pole.Chcete-li převést nebo z posloupnost, použijte List.toSeq nebo List.ofSeq.Chcete-li převést nebo z pole, použijte List.toArray nebo List.ofArray.
Další operace
Informace o dalších operací na seznamy, naleznete v tématu referenční knihovny Collections.List – modul (F#).