Megosztás a következőn keresztül:


Listák

Az F#-beli lista az azonos típusú elemek rendezett, nem módosítható sorozata. A listák alapműveleteinek elvégzéséhez használja a Lista modulban található függvényeket.

Listák létrehozása és inicializálása

A listát úgy határozhatja meg, hogy explicit módon felsorolja az elemeket pontosvesszővel elválasztva és szögletes zárójelben, ahogy az a következő kódsorban látható.

let list123 = [ 1; 2; 3 ]

Sortöréseket is elhelyezhet az elemek között, ebben az esetben a pontosvesszők megadása nem kötelező. Az utóbbi szintaxis olvashatóbb kódot eredményezhet, ha az elem inicializálási kifejezései hosszabbak, vagy ha megjegyzést szeretne fűzni az egyes elemekhez.

let list123 = [ 1; 2; 3 ]

Általában minden listaelemnek azonos típusúnak kell lennie. Kivételt képeznek azok a listák, amelyekben az elemek alaptípusként vannak megadva, lehetnek származtatott típusok. Így a következők elfogadhatók, mert mindkettő Button és CheckBox származik .Control

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

Listaelemeket úgy is definiálhat, hogy a tartomány operátora.. () által elválasztott egész számokat tartalmazó tartományt használ, ahogyan az az alábbi kódban is látható.

let list1 = [ 1..10 ]

Az üres listát szögletes zárójelek párja adja meg, és nincs közöttük semmi.

// An empty list.
let listEmpty = []

Lista létrehozásához szekvenciakifejezést is használhat. További információt a Szekvenciakifejezések című témakörben talál. Az alábbi kód például 1 és 10 közötti egész számok négyzeteinek listáját hozza létre.

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

Operátorok a listákkal való munkához

Elemeket csatolhat egy listához a :: (cons) operátorral. Ha list1 igen[2; 3; 4], az alábbi kód a következőképpen [100; 2; 3; 4]jön létrelist2:

let list2 = 100 :: list1

A kompatibilis típusokkal rendelkező listákat összefűzheti az @ operátorral, ahogyan az alábbi kódban is látható. Ha list1 igen [2; 3; 4]list2[100; 2; 3; 4], akkor ez a kód a következőképpen [2; 3; 4; 100; 2; 3; 4]jön létrelist3: .

let list3 = list1 @ list2

A listákon végzett műveletek végrehajtására szolgáló függvények a Lista modulban érhetők el.

Mivel az F#-beli listák nem módosíthatók, a módosítási műveletek új listákat hoznak létre a meglévő listák módosítása helyett.

Az F#-listák egymáshoz csatolt listákként vannak implementálva, ami azt jelenti, hogy azok a műveletek, amelyek csak a listavezetőhöz férnek hozzá, O(1), az elemhozzáférés pedig O(n).

Tulajdonságok

A listatípus a következő tulajdonságokat támogatja:

Tulajdonság Típus Leírás
Fej 'T Az első elem.
Üres 'T list Statikus tulajdonság, amely a megfelelő típus üres listáját adja vissza.
IsEmpty bool true ha a lista nem tartalmaz elemeket.
Cikk 'T A megadott index (nulla alapú) eleme.
Hossz int Az elemek száma.
Farok 'T list Az első elem nélküli lista.

Az alábbiakban néhány példát mutatunk be ezeknek a tulajdonságoknak a használatára.

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ák használata

A listákkal való programozással összetett műveleteket végezhet kis mennyiségű kóddal. Ez a szakasz a funkcionális programozáshoz fontos listák gyakori műveleteit ismerteti.

Ismétlődés listákkal

A listák egyedülállóan megfelelnek a rekurzív programozási technikáknak. Fontolja meg azt a műveletet, amelyet a lista minden elemén végre kell hajtani. Ezt rekurzív módon teheti meg, ha a lista élén dolgozik, majd átadja a lista farkát, amely egy kisebb lista, amely az eredeti lista első eleme nélkül áll, ismét a rekurzió következő szintjére.

Egy ilyen rekurzív függvény írásához használja a cons operátort (::) a mintaegyezésben, amely lehetővé teszi, hogy elválasztsa a lista fejét a faroktól.

Az alábbi példakód bemutatja, hogyan használható mintaegyeztetés egy rekurzív függvény implementálásához, amely műveleteket hajt végre egy listában.

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

Az előző kód jól működik a kis listák esetében, de nagyobb listák esetén túlcsordulhat a verem. Az alábbi kód egy gyűjtőargumentummal, a rekurzív függvények használatához használt standard technikával fejleszti a kódot. Az akkumulátor argumentum használata rekurzívsá teszi a függvény farokrészét, amely helyet takarít meg a verem számára.

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

    loop list 0

A függvény RemoveAllMultiples egy rekurzív függvény, amely két listát vesz fel. Az első lista tartalmazza azokat a számokat, amelyek többszöröseit eltávolítja a program, a második pedig az a lista, amelyből eltávolíthatja a számokat. A következő példában szereplő kód ezt a rekurzív függvényt használja az összes nem prímszám eltávolítására egy listából, így az elsődleges számok listája marad.

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)

A kimenet a következő:

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]

Modulfüggvények

A Lista modul olyan függvényeket biztosít, amelyek hozzáférnek egy lista elemeihez. A fejelem a leggyorsabb és legkönnyebben elérhető. Használja a Head tulajdonságot vagy a List.head modulfüggvényt. A lista farkához a Tail tulajdonság vagy a List.tail függvény használatával férhet hozzá. Egy elem index szerinti kereséséhez használja a List.nth függvényt . List.nth bejárja a listát. Ezért ez O(n). Ha a kód gyakran használ List.nth , érdemes lehet egy tömböt használni lista helyett. A tömbökben az elemhozzáférés O(1).

Logikai műveletek listákon

A List.isEmpty függvény határozza meg, hogy egy lista tartalmaz-e elemeket.

A List.exists függvény logikai tesztet alkalmaz egy lista elemeire, és visszaadja true , ha bármely elem megfelel a tesztnek. A List.exists2 hasonló, de két lista egymást követő elempárján működik.

Az alábbi kód bemutatja a .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)

A kimenet a következő:

For list [0; 1; 2; 3], contains zero is true

Az alábbi példa bemutatja a .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

A kimenet a következő:

Lists [1; 2; 3; 4; 5] and [5; 4; 3; 2; 1] have at least one equal element at the same position.

A List.forall parancsot akkor használhatja, ha ellenőrizni szeretné, hogy a lista összes eleme megfelel-e egy feltételnek.

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

A kimenet a következő:

true
false

Hasonlóképpen a List.forall2 meghatározza, hogy a két lista megfelelő pozícióiban lévő összes elem megfelel-e egy logikai kifejezésnek, amely minden egyes elempárt magában foglal.

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

A kimenet a következő:

true
false

Rendezési műveletek listákon

A List.sort, a List.sortBy és a List.sortWith függvény rendezési listák. A rendezési függvény határozza meg, hogy a három függvény közül melyiket használja. List.sort alapértelmezett általános összehasonlítást használ. Az általános összehasonlítás az általános összehasonlítási függvényen alapuló globális operátorokat használ az értékek összehasonlításához. Hatékonyan működik számos elemtípussal, például egyszerű numerikus típusokkal, rekordokkal, rekordokkal, diszkriminált egyesítésekkel, listákkal, tömbökkel és bármilyen implementált típussal System.IComparable. A implementálható System.IComparabletípusok esetében az általános összehasonlítás a függvényt System.IComparable.CompareTo() használja. Az általános összehasonlítás sztringekkel is működik, de kultúrafüggetlen rendezési sorrendet használ. Általános összehasonlítás nem használható nem támogatott típusok, például függvénytípusok esetében. Emellett az alapértelmezett általános összehasonlítás teljesítménye a legjobb a kis strukturált típusok esetében; nagyobb strukturált típusok esetében, amelyeket gyakran kell összehasonlítani és rendezni, fontolja meg a System.IComparable.CompareTo() módszer hatékony implementálását System.IComparable és hatékony megvalósítását.

List.sortBy egy olyan függvényt vesz fel, amely rendezési feltételként használt értéket ad vissza, és List.sortWith argumentumként egy összehasonlító függvényt vesz fel. Ez utóbbi két függvény akkor hasznos, ha olyan típusokkal dolgozik, amelyek nem támogatják az összehasonlítást, vagy ha az összehasonlítás összetettebb összehasonlító szemantikát igényel, mint a kultúratudatos sztringek esetében.

Az alábbi példa bemutatja a .List.sort

let sortedList1 = List.sort [1; 4; 8; -2; 5]
printfn "%A" sortedList1

A kimenet a következő:

[-2; 1; 4; 5; 8]

Az alábbi példa bemutatja a .List.sortBy

let sortedList2 = List.sortBy (fun elem -> abs elem) [1; 4; 8; -2; 5]
printfn "%A" sortedList2

A kimenet a következő:

[1; -2; 4; 5; 8]

A következő példa a List.sortWith. Ebben a példában az egyéni összehasonlító függvény compareWidgets először egy egyéni típusú mező összehasonlítására szolgál, majd egy másikra, ha az első mező értéke egyenlő.

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

A kimenet a következő:

[{ID = 92;
Rev = 1;}; {ID = 92;
Rev = 1;}; {ID = 100;
Rev = 2;}; {ID = 100;
Rev = 5;}; {ID = 110;
Rev = 1;}]

Keresési műveletek listákon

A listákhoz számos keresési művelet támogatott. A legegyszerűbb, a List.find segítségével megkeresheti az adott feltételnek megfelelő első elemet.

Az alábbi példakód bemutatja, hogy a lista első 5-ével osztható számának megkeresése List.find használható-e.

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

Az eredmény 5.

Ha először az elemeket kell átalakítani, hívja meg a List.pick függvényt, amely egy lehetőséget visszaadó függvényt vesz igénybe, és megkeresi az első beállítás értékét Some(x). Az elem List.pick visszaadása helyett az eredményt xadja vissza. Ha nem található egyező elem, List.pick dob.System.Collections.Generic.KeyNotFoundException Az alábbi kód a következő kód használatát List.pickmutatja be.

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

A kimenet a következő:

"b"

A keresési műveletek egy másik csoportja, a List.tryFind és a kapcsolódó függvények egy beállításértéket ad vissza. A List.tryFind függvény egy lista első olyan elemét adja vissza, amely megfelel egy feltételnek, ha létezik ilyen elem, de a beállítás értéke None , ha nem. A List.tryFindIndex változat az elem indexét adja vissza, ha van ilyen, és nem magát az elemet. Ezeket a függvényeket az alábbi kód szemlélteti.

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."

A kimenet a következő:

The first even value is 22.
The first even value is at position 8.

Aritmetikai műveletek listákon

Az olyan gyakori aritmetikai műveletek, mint például az összeg és az átlag, a Lista modulba vannak beépítve. A List.sum használatához a listaelem típusának támogatnia kell az + operátort, és nulla értékkel kell rendelkeznie. Minden beépített aritmetikai típus megfelel ezeknek a feltételeknek. A List.average használatához az elemtípusnak támogatnia kell a maradék nélküli osztást, amely kizárja az integráltípusokat, de lehetővé teszi a lebegőpontos típusok működését. A List.sumBy és a List.averageBy függvény egy függvényt vesz fel paraméterként, és ennek a függvénynek az eredményeit használja az összeg vagy az átlag értékeinek kiszámításához.

Az alábbi kód bemutatja az , List.sumByés List.averagea List.sum.

// 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

A kimenet a következő: 1.000000.

Az alábbi kód a következő kód használatát List.averageBymutatja be.

let avg2 = List.averageBy (fun elem -> float elem) [1 .. 10]
printfn "%f" avg2

A kimenet a következő: 5.5.

Listák és csuples

A csuplokat tartalmazó listák zip és unzip függvényekkel módosíthatók. Ezek a függvények egyetlen értékekből álló két listát egyesítenek egy halmazlistába, vagy egyetlen értéklistába választanak el egy halmazlistát. A legegyszerűbb List.zip függvény az egyes elemek két listáját veszi fel, és egyetlen rekordpár-listát hoz létre. Egy másik verzió, a List.zip3 három lista egyetlen elemből áll, és egyetlen listát hoz létre a három elemet tartalmazó listákból. Az alábbi példakód bemutatja a használatát List.zip.

let list1 = [ 1; 2; 3 ]
let list2 = [ -1; -2; -3 ]
let listZip = List.zip list1 list2
printfn "%A" listZip

A kimenet a következő:

[(1, -1); (2, -2); (3; -3)]

Az alábbi példakód bemutatja a használatát List.zip3.

let list3 = [ 0; 0; 0]
let listZip3 = List.zip3 list1 list2 list3
printfn "%A" listZip3

A kimenet a következő:

[(1, -1, 0); (2, -2, 0); (3, -3, 0)]

A megfelelő unzip verziók, a List.unzip és a List.unzip3, a rekordok listáját és a visszatérési listákat egy rekordban jelenítik meg, ahol az első lista tartalmazza az összes elemet, amelyek elsőként voltak az egyes rekordokban, a második lista pedig az egyes rekordok második elemét tartalmazza, és így tovább.

Az alábbi példakód a List.unzip használatát mutatja be.

let lists = List.unzip [(1,2); (3,4)]
printfn "%A" lists
printfn "%A %A" (fst lists) (snd lists)

A kimenet a következő:

([1; 3], [2; 4])
[1; 3] [2; 4]

Az alábbi példakód a List.unzip3 használatát mutatja be.

let listsUnzip3 = List.unzip3 [(1,2,3); (4,5,6)]
printfn "%A" listsUnzip3

A kimenet a következő:

([1; 4], [2; 5], [3; 6])

Működés listaelemeken

Az F# számos műveletet támogat a listaelemeken. A legegyszerűbb a List.iter, amely lehetővé teszi egy függvény meghívását a lista minden elemén. A változatok közé tartozik a List.iter2, amely lehetővé teszi, hogy műveletet hajtson végre két lista elemein, a List.iteri-en, ami hasonló List.iter azzal a különbségtel, hogy az egyes elemek indexe argumentumként lesz átadva az egyes elemekhez hívott függvénynek, és a List.iteri2, amely a funkció List.iter2 és List.iteria . Az alábbi példakód ezeket a függvényeket szemlélteti.

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

A kimenet a következő:

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

A listaelemeket átalakító másik gyakran használt függvény a List.map, amely lehetővé teszi, hogy egy függvényt alkalmazzon a lista minden elemére, és az összes eredményt egy új listába helyezze. A List.map2 és a List.map3 olyan változatok, amelyek több listát is használnak. A List.mapi és a List.mapi2 függvényt akkor is használhatja, ha az elem mellett a függvénynek az egyes elemek indexét is át kell adni. Az egyetlen különbség a két lista között List.mapi2List.mapi és az, hogy List.mapi2 működik. Az alábbi példa a List.map-et szemlélteti.

let list1 = [1; 2; 3]
let newList = List.map (fun x -> x + 1) list1
printfn "%A" newList

A kimenet a következő:

[2; 3; 4]

Az alábbi példa a következő parancs használatát List.map2mutatja be.

let list1 = [1; 2; 3]
let list2 = [4; 5; 6]
let sumList = List.map2 (fun x y -> x + y) list1 list2
printfn "%A" sumList

A kimenet a következő:

[5; 7; 9]

Az alábbi példa a következő parancs használatát List.map3mutatja be.

let newList2 = List.map3 (fun x y z -> x + y + z) list1 list2 [2; 3; 4]
printfn "%A" newList2

A kimenet a következő:

[7; 10; 13]

Az alábbi példa a következő parancs használatát List.mapimutatja be.

let newListAddIndex = List.mapi (fun i x -> x + i) list1
printfn "%A" newListAddIndex

A kimenet a következő:

[1; 3; 5]

Az alábbi példa a következő parancs használatát List.mapi2mutatja be.

let listAddTimesIndex = List.mapi2 (fun i x y -> (x + y) * i) list1 list2
printfn "%A" listAddTimesIndex

A kimenet a következő:

[0; 7; 18]

A List.collect hasonló List.map, azzal a kivételrel, hogy minden elem létrehoz egy listát, és az összes lista össze van fűzve egy végső listába. Az alábbi kódban a lista minden eleme három számot hoz létre. Ezek mindegyike egy listában van összegyűjtve.

let collectList = List.collect (fun x -> [for i in 1..3 -> x * i]) list1
printfn "%A" collectList

A kimenet a következő:

[1; 2; 3; 2; 4; 6; 3; 6; 9]

Használhatja a List.filtert is, amely logikai feltételt vesz igénybe, és létrehoz egy új listát, amely csak az adott feltételnek megfelelő elemekből áll.

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

Az eredményként kapott lista a következő [2; 4; 6]: .

A List.choose térkép és szűrő kombinációjával egyszerre alakíthatja át és jelölheti ki az elemeket. List.choose egy olyan függvényt alkalmaz, amely egy lista minden elemére visszaad egy lehetőséget, és az elemek eredményének új listáját adja vissza, amikor a függvény visszaadja a beállítás értékét Some.

Az alábbi kód bemutatja, hogyan lehet List.choose nagybetűs szavakat kiválasztani a szavak listájából.

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

A kimenet a következő:

["Rome's"; "Bob's"]

Több listán való működés

A listák összekapcsolhatók. Ha két listát szeretne egybe illeszteni, használja a List.append parancsot. Ha kétnál több listához szeretne csatlakozni, használja a List.concat parancsot.

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

Összecsukási és beolvasási műveletek

Egyes listaműveletek az összes listaelem közötti függéseket foglalják magukban. Az összecsukási és a beolvasási műveletek hasonlóak List.iter , és List.map ebben az esetben minden egyes elemhez meghív egy függvényt, de ezek a műveletek egy további paramétert biztosítanak, az akkumulátort , amely a számításon keresztül adatokat hordoz.

Használatával List.fold számítást végezhet egy listában.

Az alábbi példakód a List.fold különböző műveletek végrehajtására való használatát mutatja be.

A lista bejárva; az akkumulátor acc egy olyan érték, amely a számítás során halad tovább. Az első argumentum felveszi az akkumulátort és a listaelemet, és visszaadja az adott listaelem számításának időközi eredményét. A második argumentum az akkumulátor kezdeti értéke.

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

A függvények azon verziói, amelyekben a függvénynévben számjegy szerepel, több listában is működnek. A List.fold2 például két listában végez számításokat.

Az alábbi példa bemutatja a .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 és a List.scan abban különbözik, hogy List.fold a plusz paraméter végső értékét adja vissza, de List.scan a plusz paraméter köztes értékeinek listáját adja vissza (a végső értékkel együtt).

Mindegyik függvény tartalmaz egy fordított változatot, például a List.foldBacket, amely a lista bejárási sorrendjében és az argumentumok sorrendjében különbözik. List.foldList.foldBack Emellett olyan változatokkal is rendelkezik, mint a List.fold2 és a List.foldBack2, amelyek két azonos hosszúságú listát vesznek fel. Az egyes elemeken végrehajtó függvény mindkét lista megfelelő elemeit használhatja bizonyos műveletek végrehajtásához. A két lista elemtípusai eltérőek lehetnek, mint az alábbi példában, amelyben az egyik lista egy bankszámla tranzakciós összegeket tartalmaz, a másik lista pedig a tranzakció típusát tartalmazza: betétet vagy készpénzfelvételt.

// 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

Az olyan számítások esetében, mint az összegzés, és List.foldBack ugyanolyan hatással vannak, List.fold mert az eredmény nem függ a bejárás sorrendjétől. Az alábbi példában List.foldBack a lista elemeinek hozzáadására szolgál.

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

Az alábbi példa a bankszámla példájára tér vissza. Ezúttal egy új tranzakciótípust ad hozzá: egy kamatszámítást. A záró egyenleg most a tranzakciók sorrendjétől függ.

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

A List.reduce függvény némileg hasonlóList.fold, és List.scanazzal a kivételrel, hogy ahelyett, hogy külön akkumulátort használna, egy olyan függvényt vesz fel, List.reduce amely az elemtípus két argumentumát veszi fel egyetlen helyett, és az egyik argumentum az akkumulátorként működik, ami azt jelenti, hogy a számítás köztes eredményét tárolja. List.reduce az első két listaelemen való működéssel kezdődik, majd a művelet eredményét használja a következő elemmel együtt. Mivel nincs külön akkumulátor, amelynek saját típusa van, csak akkor használhatóList.fold, List.reduce ha az akkumulátor és az elemtípus ugyanazzal a típussal rendelkezik. Az alábbi kód bemutatja a .List.reduce List.reduce kivételt eredményez, ha a megadott lista nem tartalmaz elemeket.

A következő kódban a lambda kifejezés első hívása a 2. és a 4. argumentumot kapja, és 6-ot ad vissza, a következő hívás pedig a 6 és a 10 argumentumot kapja, így az eredmény 16 lesz.

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

Konvertálás listák és más gyűjteménytípusok között

A List modul függvényeket biztosít a sorozatokra és tömbökre való konvertáláshoz és azokból való konvertáláshoz. Sorozattá alakításához vagy sorozatból való konvertáláshoz használja a List.toSeq vagy a List.ofSeq parancsot. Tömbre vagy tömbből való konvertáláshoz használja a List.toArray vagy a List.ofArray parancsot.

További műveletek

További információk a listákon végzett további műveletekről: könyvtárhivatkozási témakör Listamodul.

Lásd még