F # - listy

W języku F # lista jest uporządkowaną, niezmienną serią elementów tego samego typu. Jest to do pewnego stopnia równoważne strukturze danych z połączonej listy.

Moduł F #, Microsoft.FSharp.Collections.List,ma wspólne operacje na listach. Jednak F # importuje ten moduł automatycznie i udostępnia go każdej aplikacji F #.

Tworzenie i inicjowanie listy

Poniżej przedstawiono różne sposoby tworzenia list -

  • Korzystanie z listy literals.

  • Za pomocą cons (: :) operator.

  • Używając List.init metoda modułu List.

  • Korzystanie z niektórych syntactic constructs nazywa List Comprehensions.

Lista literałów

W tej metodzie wystarczy określić rozdzieloną średnikami sekwencję wartości w nawiasach kwadratowych. Na przykład -

let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

Wady (: :) Operator

Za pomocą tej metody można dodać niektóre wartości, poprzedzając lub cons-ingdo istniejącej listy przy użyciu operatora ::. Na przykład -

let list2 = 1::2::3::4::5::6::7::8::9::10::[];;

[] oznacza pustą listę.

Lista metody inicjalizacji

Metoda List.init modułu List jest często używana do tworzenia list. Ta metoda ma typ -

val init : int -> (int -> 'T) -> 'T list

Pierwszy argument to żądana długość nowej listy, a drugi argument to funkcja inicjująca, która generuje pozycje na liście.

Na przykład,

let list5 = List.init 5 (fun index -> (index, index * index, index * index * index))

Tutaj funkcja indeksu generuje listę.

Lista ujęć

Listy składane to specjalne konstrukcje składniowe używane do generowania list.

Składnia składni listy F # występuje w dwóch formach - zakresów i generatorów.

Zakresy mają konstrukcje - [start .. end] i [start .. step .. end]

Na przykład,

let list3 = [1 .. 10]

Generatory mają konstrukcję - [for x in collection do ... yield expr]

Na przykład,

let list6 = [ for a in 1 .. 10 do yield (a * a) ]

Ponieważ yield słowo kluczowe wypycha pojedynczą wartość na listę, słowo kluczowe, yield!, umieszcza zbiór wartości na liście.

Poniższa funkcja demonstruje powyższe metody -

Przykład

(* using list literals *)
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The list: %A" list1

(*using cons operator *)
let list2 = 1 :: 2 :: 3 :: []
printfn "The list: %A" list2

(* using range constructs*)
let list3 = [1 .. 10]
printfn "The list: %A" list3

(* using range constructs *)
let list4 = ['a' .. 'm']
printfn "The list: %A" list4

(* using init method *)
let list5 = List.init 5 (fun index -> (index, index * index, index * index * index))
printfn "The list: %A" list5

(* using yield operator *)
let list6 = [ for a in 1 .. 10 do yield (a * a) ]
printfn "The list: %A" list6

(* using yield operator *)
let list7 = [ for a in 1 .. 100 do if a % 3 = 0 && a % 5 = 0 then yield a]
printfn "The list: %A" list7

(* using yield! operator *)
let list8 = [for a in 1 .. 3 do yield! [ a .. a + 3 ] ]
printfn "The list: %A" list8

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The list: [1; 2; 3]
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The list: ['a'; 'b'; 'c'; 'd'; 'e'; 'f'; 'g'; 'h'; 'i'; 'j'; 'k'; 'l'; 'm']
The list: [(0, 0, 0); (1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64)]
The list: [1; 4; 9; 16; 25; 36; 49; 64; 81; 100]
The list: [15; 30; 45; 60; 75; 90]
The list: [1; 2; 3; 4; 2; 3; 4; 5; 3; 4; 5; 6]

Właściwości typu danych listy

W poniższej tabeli przedstawiono różne właściwości typu danych listy -

własność Rodzaj Opis
Głowa „T Pierwszy element.
Pusty Lista 'T Właściwość statyczna, która zwraca pustą listę odpowiedniego typu.
Jest pusty bool true jeśli lista nie zawiera elementów.
Pozycja „T Element o określonym indeksie (liczony od zera).
Długość int Liczba elementów.
Ogon Lista 'T Lista bez pierwszego elementu.

Poniższy przykład pokazuje użycie tych właściwości -

Przykład

let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]

// Use of 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))

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

list1.IsEmpty is false
list1.Length is 8
list1.Head is 2
list1.Tail.Head is 4
list1.Tail.Tail.Head is 6
list1.Item(1) is 4

Podstawowe operatory na liście

Poniższa tabela przedstawia podstawowe operacje na typie danych listy -

Wartość Opis
dołącz: 'Lista T →' Lista T → 'Lista T. Zwraca nową listę zawierającą elementy pierwszej listy, po których następują elementy drugiej.
średnia: 'T lista → ^ T Zwraca średnią elementów na liście.
średnia Przez: ('T → ^ U) →' T lista → ^ U Zwraca średnią z elementów wygenerowanych przez zastosowanie funkcji do każdego elementu listy.
wybierz: (opcja 'T →' U) → 'Lista T →' Lista U Stosuje daną funkcję do każdego elementu listy. Zwraca listę zawierającą wyniki dla każdego elementu, z którego funkcja zwracaSome.
zbierać: ('T →' Lista U) → 'Lista T →' Lista U Do każdego elementu listy stosuje daną funkcję. Łączy wszystkie wyniki i zwraca połączoną listę.
concat: seq <'T lista> →' T lista Zwraca nową listę, która zawiera elementy każdej z list w kolejności.
puste: 'T lista Zwraca pustą listę podanego typu.
istnieje: ('T → bool) →' T lista → bool Sprawdza, czy którykolwiek element listy spełnia podany predykat.
istnieje2: ('T1 →' T2 → bool) → 'Lista T1 →' Lista T2 → bool Sprawdza, czy jakakolwiek para odpowiednich elementów list spełnia podany predykat.
filtr: ('T → bool) →' T lista → 'T lista Zwraca nową kolekcję zawierającą tylko elementy kolekcji, dla których zwraca dany predykat true.
znajdź: ('T → bool) →' Lista T → 'T Zwraca pierwszy element, dla którego zwraca dana funkcja true.
findIndex: ('T → bool) →' T lista → int Zwraca indeks pierwszego elementu na liście, który spełnia podany predykat.
fold: ('Stan →' T → 'Stan) →' Stan → 'Lista T →' Stan Stosuje funkcję do każdego elementu kolekcji, tworząc wątek argumentu akumulatora przez obliczenia. Ta funkcja przyjmuje drugi argument i stosuje do niego funkcję oraz pierwszy element listy. Następnie przekazuje ten wynik do funkcji wraz z drugim elementem i tak dalej. Na koniec zwraca wynik końcowy. Jeśli funkcją wejściową jest f, a elementy to i0 ... iN, to ta funkcja oblicza f (... (fs i0) i1 ...) iN.
fold2: ('Stan →' T1 → 'T2 →' Stan) → 'Stan →' Lista T1 → 'Lista T2 →' Stan Stosuje funkcję do odpowiednich elementów dwóch kolekcji, tworząc wątek argumentu akumulatora przez obliczenia. Kolekcje muszą mieć identyczne rozmiary. Jeśli funkcją wejściową jest f, a elementy to i0 ... iN oraz j0 ... jN, to ta funkcja oblicza f (... (fs i0 j0) ...) iN jN.
foldBack: ('T →' Stan → 'Stan) →' Lista T → 'Stan →' Stan Stosuje funkcję do każdego elementu kolekcji, tworząc wątek argumentu akumulatora przez obliczenia. Jeśli funkcja wejściowa isf, a elementy to i0 ... iN, oblicza f i0 (... (f iN s)).
foldBack2: ('T1 →' T2 → 'Stan →' Stan) → 'Lista T1 →' Lista T2 → 'Stan →' Stan Stosuje funkcję do odpowiednich elementów dwóch kolekcji, tworząc wątek argumentu akumulatora przez obliczenia. Kolekcje muszą mieć identyczne rozmiary. Jeśli funkcją wejściową jest f, a elementy to i0 ... iN oraz j0 ... jN, to ta funkcja oblicza f i0 j0 (... (f iN jN s)).
forall: ('T → bool) →' T lista → bool Sprawdza, czy wszystkie elementy kolekcji spełniają podany predykat.
forall2: ('T1 →' T2 → bool) → 'Lista T1 →' Lista T2 → bool Sprawdza, czy wszystkie odpowiadające elementy kolekcji spełniają podany predykat parami.
head: 'T lista →' T Zwraca pierwszy element listy.
init: int → (int → 'T) →' T list Tworzy listę poprzez wywołanie danego generatora w każdym indeksie.
isEmpty: 'T lista → bool Zwroty true jeśli lista nie zawiera elementów, false Inaczej.
iter: ('T → jednostka) →' Lista T → jednostka Stosuje daną funkcję do każdego elementu kolekcji.
iter2: ('T1 →' T2 → jednostka) → 'Lista T1 →' Lista T2 → jednostka Stosuje daną funkcję do dwóch kolekcji jednocześnie. Kolekcje muszą mieć identyczny rozmiar.
iteri: (int → 'T → jednostka) →' Lista T → jednostka Stosuje daną funkcję do każdego elementu kolekcji. Liczba całkowita przekazana do funkcji wskazuje indeks elementu.
iteri2: (int → 'T1 →' T2 → jednostka) → 'Lista T1 →' Lista T2 → jednostka Stosuje daną funkcję do dwóch kolekcji jednocześnie. Kolekcje muszą mieć identyczny rozmiar. Liczba całkowita przekazana do funkcji wskazuje indeks elementu.
długość: 'T lista → wew Zwraca długość listy.
mapa: ('T →' U) → 'Lista T →' Lista U Tworzy nową kolekcję, której elementy są wynikiem zastosowania danej funkcji do każdego z elementów kolekcji.
mapa2: ('T1 →' T2 → 'U) →' Lista T1 → 'Lista T2 →' Lista U Tworzy nową kolekcję, której elementy są wynikiem zastosowania danej funkcji do odpowiednich elementów dwóch kolekcji parami.
map3: ('T1 →' T2 → 'T3 →' U) → 'Lista T1 →' Lista T2 → 'Lista T3 →' Lista U Tworzy nową kolekcję, której elementy są wynikiem zastosowania danej funkcji do odpowiednich elementów trzech kolekcji jednocześnie.
mapi: (int → 'T →' U) → 'Lista T →' Lista U Tworzy nową kolekcję, której elementy są wynikiem zastosowania danej funkcji do każdego z elementów kolekcji. Indeks w postaci liczby całkowitej przekazany do funkcji wskazuje indeks (od 0) transformowanego elementu.
mapi2: (int → 'T1 →' T2 → 'U) →' Lista T1 → 'Lista T2 →' Lista U Podobnie jak List.mapi, ale mapuje odpowiednie elementy z dwóch list o równej długości.
max: 'T lista →' T Zwraca największy ze wszystkich elementów listy w porównaniu przy użyciu Operators.max.
maxBy: ('T →' U) → 'Lista T →' T Zwraca największy ze wszystkich elementów listy w porównaniu przy użyciu metody Operators.max w wyniku funkcji.
min: 'T lista →' T Zwraca najniższy ze wszystkich elementów listy w porównaniu przy użyciu Operators.min.
min Przez: ('T →' U) → 'Lista T →' T Zwraca najniższy ze wszystkich elementów listy w porównaniu przy użyciu Operators.min w wyniku funkcji
nth: 'T lista → int →' T Indeksy do listy. Pierwszy element ma indeks 0.
ofArray: 'T [] →' T lista Tworzy listę z podanej tablicy.
ofSeq: seq <'T> →' T list Tworzy nową listę z podanego wyliczalnego obiektu.
partycja: ('T → bool) →' T lista * 'T lista Dzieli kolekcję na dwie kolekcje zawierające elementy, dla których zwraca dany predykat true i false odpowiednio.
permute: (int → int) → 'T lista →' T lista Zwraca listę ze wszystkimi elementami permutowanymi zgodnie z określoną permutacją.
wybierz: (opcja 'T →' U) → 'Lista T →' U Stosuje daną funkcję do kolejnych elementów, zwracając pierwszy wynik, gdy funkcja zwraca Some za jakąś wartość.
zmniejsz: ('T →' T → 'T) →' Lista T → 'T Stosuje funkcję do każdego elementu kolekcji, tworząc wątek argumentu akumulatora przez obliczenia. Ta funkcja stosuje określoną funkcję do pierwszych dwóch elementów listy. Następnie przekazuje ten wynik do funkcji wraz z trzecim elementem i tak dalej. Na koniec zwraca wynik końcowy. Jeśli funkcją wejściową jest f, a elementy są i0 ... iN, to funkcja ta oblicza f (... (f i0 i1) i2 ...) iN.
redukcjaBack: ('T →' T → 'T) →' Lista T → 'T Stosuje funkcję do każdego elementu kolekcji, tworząc wątek argumentu akumulatora przez obliczenia. Jeśli funkcja wejściowa isf, a elementy to i0 ... iN, to funkcja ta oblicza f i0 (... (f iN-1 iN)).
replicate: (int → 'T →' T list) Tworzy listę poprzez wywołanie danego generatora w każdym indeksie.
rev: 'Lista T →' Lista T. Zwraca nową listę z elementami w odwrotnej kolejności.
skanowanie: ('Stan →' T → 'Stan) →' Stan → 'Lista T →' Lista stanów Stosuje funkcję do każdego elementu kolekcji, tworząc wątek argumentu akumulatora przez obliczenia. Ta funkcja przyjmuje drugi argument i stosuje do niego określoną funkcję oraz pierwszy element listy. Następnie przekazuje ten wynik do funkcji wraz z drugim elementem i tak dalej. Na koniec zwraca listę wyników pośrednich i wyniku końcowego.
scanBack: ('T →' Stan → 'Stan) →' Lista T → 'Stan →' Lista stanów Podobnie jak foldBack, ale zwraca wyniki pośrednie i końcowe
sortuj: 'T lista →' T lista Sortuje podaną listę za pomocą Operators.compare.
sortBy: ('T →' Key) → 'T list →' T list Sortuje podaną listę za pomocą kluczy podanych przez daną projekcję. Klucze są porównywane za pomocą Operators.compare.
sortWith: ('T →' T → int) → 'T lista →' T lista Sortuje podaną listę przy użyciu podanej funkcji porównania.
suma: ^ T lista → ^ T Zwraca sumę elementów na liście.
sumBy: ('T → ^ U) →' T lista → ^ U Zwraca sumę wyników wygenerowanych przez zastosowanie funkcji do każdego elementu listy.
ogon: 'Lista T →' Lista T. Zwraca listę wejściową bez pierwszego elementu.
toArray: 'T lista →' T [] Tworzy tablicę z podanej listy.
toSeq: 'T list → seq <' T> Wyświetla podaną listę jako sekwencję.
tryFind: ('T → bool) →' Lista T → opcja 'T Zwraca pierwszy element, dla którego zwraca dana funkcja true. PowrótNone jeśli taki element nie istnieje.
tryFindIndex: ('T → bool) →' T lista → opcja int Zwraca indeks pierwszego elementu na liście, który spełnia podany predykat. PowrótNone jeśli taki element nie istnieje.
tryPick: (opcja 'T →' U) → 'Lista T → opcja' U Stosuje daną funkcję do kolejnych elementów, zwracając pierwszy wynik, gdy funkcja zwraca Someza jakąś wartość. Jeśli taki element nie istnieje, powróćNone.
rozpakuj: ('T1 *' T2) lista → 'T1 lista *' Lista T2 Dzieli listę par na dwie listy.
unzip3: ('T1 *' T2 * 'T3) lista →' Lista T1 * 'Lista T2 *' Lista T3 Dzieli listę trójek na trzy listy.
zip: 'Lista T1 →' Lista T2 → ('T1 *' T2) lista Łączy dwie listy w listę par. Obie listy muszą mieć równe długości.
zip3: 'Lista T1 →' Lista T2 → 'Lista T3 → (' T1 * 'T2 *' T3) lista Łączy trzy listy w listę trójek. Listy muszą mieć równe długości.

Poniższe przykłady pokazują zastosowania powyższych funkcji -

Przykład 1

Ten program pokazuje rekurencyjne odwracanie listy -

let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
printfn "The original list: %A" list1

let reverse lt =
   let rec loop acc = function
      | [] -> acc
      | hd :: tl -> loop (hd :: acc) tl
   loop [] lt

printfn "The reversed list: %A" (reverse list1)

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

The original list: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]

Możesz jednak użyć rev funkcja modułu w tym samym celu -

let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
printfn "The original list: %A" list1
printfn "The reversed list: %A" (List.rev list1)

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

The original list: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]

Przykład 2

Ten program pokazuje filtrowanie listy przy użyciu rozszerzenia List.filter metoda -

let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The list: %A" list1
let list2 = list1 |> List.filter (fun x -> x % 2 = 0);;
printfn "The Filtered list: %A" list2

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The Filtered list: [2; 4; 6; 8; 10]

Przykład 3

Plik List.map metoda mapuje listę z jednego typu na inny -

let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The list: %A" list1
let list2 = list1 |> List.map (fun x -> (x * x).ToString());;
printfn "The Mapped list: %A" list2

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The Mapped list: ["1"; "4"; "9"; "16"; "25"; "36"; "49"; "64"; "81"; "100"]

Przykład 4

Plik List.append metoda, a operator @ dołącza jedną listę do drugiej -

let list1 = [1; 2; 3; 4; 5 ]
let list2 = [6; 7; 8; 9; 10]
let list3 = List.append list1 list2

printfn "The first list: %A" list1
printfn "The second list: %A" list2
printfn "The appened list: %A" list3

let lt1 = ['a'; 'b';'c' ]
let lt2 = ['e'; 'f';'g' ]
let lt3 = lt1 @ lt2

printfn "The first list: %A" lt1
printfn "The second list: %A" lt2
printfn "The appened list: %A" lt3

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

The first list: [1; 2; 3; 4; 5]
The second list: [6; 7; 8; 9; 10]
The appened list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The first list: ['a'; 'b'; 'c']
The second list: ['e'; 'f'; 'g']
The appened list: ['a'; 'b'; 'c'; 'e'; 'f'; 'g']

Przykład 5

Plik List.sortmetoda sortuje listę. PlikList.sum zwraca sumę elementów na liście i List.average metoda podaje średnią elementów na liście -

let list1 = [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0]
printfn "The list: %A" list1

let list2 = List.sort list1
printfn "The sorted list: %A" list2

let s = List.sum list1
let avg = List.average list1
printfn "The sum: %f" s
printfn "The average: %f" avg

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

The list: [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0]
The sorted list: [-10.0; -4.5; 0.0; 2.0; 8.0; 9.0; 11.2]
The sum: 15.700000
The average: 2.242857

Operacja „zwijania” stosuje funkcję do każdego elementu na liście, agreguje wynik funkcji w zmiennej akumulatorowej i zwraca akumulator jako wynik operacji zwinięcia.

Przykład 6

Plik List.fold metoda stosuje funkcję do każdego elementu od lewej do prawej, podczas gdy List.foldBack stosuje funkcję do każdego elementu od prawej do lewej.

let sumList list = List.fold (fun acc elem -> acc + elem) 0 list
printfn "Sum of the elements of list %A is %d." [ 1 .. 10 ] (sumList [ 1 .. 10 ])

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

Sum of the elements of list [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] is 55.