Eine Liste ist eine geordnete Sammlung von Werten desselben Typs.
let numbers = [ 1 ; 2 ; 3 ; 4 ; 5 ] // int list
let names = [ "Anna" ; "Ben" ; "Carla" ] // string list
Erstellung
let numbers = [ 1 ; 2 ; 3 ; 4 ]
let emptyList = []
let emptyNumbers : int list = []
let numbers = [ 1 .. 10 ]
let evenNumbers = [ 2 .. 2 .. 10 ]
Zugriff
Man kann mit list[index] auf ein Element zugreifen.
let numbers = [ 10 ; 20 ; 30 ; 40 ]
let first = numbers [ 0 ]
let second = numbers [ 1 ]
Wenn der Index nicht existiert, gibt es einen Fehler.
Head und Tail
List.head gibt das erste Element einer Liste zurück.
let numbers = [ 10 ; 20 ; 30 ]
let first = List.head numbers
Achtung : Bei einer leeren Liste gibt List.head einen Fehler.Sauberer ist oft Pattern Matching: let getFirst list =
match list with
| [] -> None
| x :: _ -> Some x
List.tail gibt die Liste ohne das erste Element zurück.
let numbers = [ 10 ; 20 ; 30 ]
let rest = List.tail numbers
Auch hier gilt: Bei einer leeren Liste gibt es einen Fehler. Sauber mit Pattern Matching: let getTail list =
match list with
| [] -> []
| _ :: xs -> xs
Cons Operator ::
Der Cons Operator :: fügt ein Element vorne an eine Liste an.
let numbers = [ 2 ; 3 ; 4 ]
let newNumbers = 1 :: numbers
Wichtig : Das Element links muss den gleichen Typ haben wie die Elemente der Liste.
Der Cons Operator wird auch oft in Pattern Matching verwendet:
let describe list =
match list with
| [] -> "Die Liste ist leer"
| x :: xs -> $ "Erstes Element: {x}, Rest: {xs}"
describe [ 1 ; 2 ; 3 ]
Append Operator @
Der Append Operator @ verbindet zwei Listen.
let list1 = [ 1 ; 2 ; 3 ]
let list2 = [ 4 ; 5 ; 6 ]
let combined = list1 @ list2
List Comprehensions
List Comprehensions sind eine kompakte Möglichkeit, Listen zu erzeugen.
[ for x in collection do yield expression ]
Beispiel:
let squares = [ for x in 1 .. 5 do yield x * x ]
Mit Bedingung
let evenNumbers =
[ for x in 1 .. 10 do
if x % 2 = 0 then
yield x ]
Mehrere yield
Man kann pro Durchlauf mehrere Werte erzeugen.
let numbers =
[ for x in 1 .. 3 do
yield x
yield x * 10 ]
yield!
yield! fügt eine ganze Liste in die neue Liste ein.
let values =
[ for x in 1 .. 3 do
yield ! [ x ; x * x ] ]
Listenfunktionen
List.map
List.map verändert jedes Element einer Liste nach einer Regel.
let numbers = [ 1 ; 2 ; 3 ; 4 ]
let doubled =
numbers |> List.map (fun x -> x * 2 )
let names = [ "anna" ; "ben" ; "carla" ]
let upperNames =
names |> List.map (fun name -> name.ToUpper ())
type Student = {
Name : string
Grade : float
}
let students = [
{ Name = "Anna" ; Grade = 5.5 }
{ Name = "Ben" ; Grade = 4.0 }
{ Name = "Carla" ; Grade = 3.5 }
]
let names =
students |> List.map (fun student -> student.Name )
List.filter
List.filter behält nur Elemente, die eine Bedingung erfüllen.
let numbers = [ 1 ; 2 ; 3 ; 4 ; 5 ; 6 ]
let evenNumbers =
numbers |> List.filter (fun x -> x % 2 = 0 )
let grades = [ 5.5 ; 4.0 ; 3.5 ; 6.0 ; 2.5 ]
let passedGrades =
grades |> List.filter (fun grade -> grade >= 4.0 )
let passedStudents =
students |> List.filter (fun student -> student.Grade >= 4.0 )
List.length
List.length gibt die Anzahl Elemente zurück.
let numbers = [ 10 ; 20 ; 30 ]
let count = numbers |> List.length
let names = [ "Anna" ; "Ben" ; "Carla" ; "Daniel" ]
let amount = names |> List.length
let empty = [] |> List.length
List.sum
List.sum addiert alle Elemente einer numerischen Liste.
let numbers = [ 1 ; 2 ; 3 ; 4 ]
let total = numbers |> List.sum
let prices = [ 10.50 ; 20.0 ; 5.25 ]
let totalPrice = prices |> List.sum
List.sumBy
List.sumBy berechnet zuerst pro Element einen Wert und summiert diese Werte danach.
type Product = {
Name : string
Price : float
Amount : int
}
let products = [
{ Name = "Book" ; Price = 20.0 ; Amount = 2 }
{ Name = "Pen" ; Price = 2.5 ; Amount = 4 }
{ Name = "Bag" ; Price = 50.0 ; Amount = 1 }
]
let total =
products |> List.sumBy (fun product -> product.Price * float product.Amount )
List.min und List.max
Gibt das kleinste bzw. das grösste Element zurück.
let numbers = [ 5 ; 2 ; 9 ; 1 ; 7 ]
let minimum = numbers |> List.min
let maximum = numbers |> List.max
Achtung : Bei einer leeren Liste gibt es einen Fehler.
List.minBy und List.maxBy
List.minBy gibt das Element zurück, bei dem ein berechneter Wert am kleinsten ist.
let cheapestProduct =
products |> List.minBy (fun product -> product.Price )
List.maxBy gibt das Element zurück, bei dem ein berechneter Wert am grössten ist.
let mostExpensiveProduct =
products |> List.maxBy (fun product -> product.Price )
List.rev
List.rev dreht die Reihenfolge einer Liste um. Die ursprüngliche Liste wird nicht verändert.
let numbers = [ 1 ; 2 ; 3 ; 4 ]
let reversed =
numbers |> List.rev
let names = [ "Anna" ; "Ben" ; "Carla" ]
let reversedNames =
names |> List.rev
List.sort
List.sort sortiert eine Liste aufsteigend.
let numbers = [ 5 ; 1 ; 9 ; 2 ]
let sorted =
numbers |> List.sort
let names = [ "Carla" ; "Anna" ; "Ben" ]
let sortedNames =
names |> List.sort
List.sortBy
List.sortBy sortiert nach einem berechneten Wert.
let studentsByGrade =
students |> List.sortBy (fun student -> student.Grade )
let studentsByName =
students |> List.sortBy (fun student -> student.Name )
List.sortDescending
List.sortDescending sortiert eines Liste absteigend.
let numbers = [ 5 ; 1 ; 9 ; 2 ]
let sortedDescending =
numbers |> List.sortDescending
let names = [ "Carla" ; "Anna" ; "Ben" ]
let sortedNames =
names |> List.sortDescending
List.sortDescendingBy
let studentsBestFirst =
students |> List.sortByDescending (fun student -> student.Grade )
List.zip
List.zip verbindet zwei Listen elementweise zu Tupeln.
let names = [ "Anna" ; "Ben" ; "Carla" ]
let grades = [ 5.5 ; 4.0 ; 3.5 ]
let combined =
List.zip names grades
Wenn die Listen unterschiedlich lang sind, gibt List.zip einen Fehler.
List.forAll
List.forall prüft, ob alle Elemente eine Bedingung erfüllen.
let grades = [ 5.0 ; 4.5 ; 6.0 ]
let allPassed =
grades |> List.forall (fun grade -> grade >= 4.0 )
List.exists
List.exists prüft, ob mindestens ein Element eine Bedingung erfüllt.
let grades = [ 5.0 ; 3.5 ; 4.5 ]
let hasFailedGrade =
grades |> List.exists (fun grade -> grade < 4.0 )
List.reduce
List.reduce fasst eine Liste zu einem einzelnen Wert zusammen.
let numbers = [ 1 ; 2 ; 3 ; 4 ]
let total =
numbers |> List.reduce (fun acc x -> acc + x )
let maximum =
numbers |> List.reduce (fun acc x -> if x > acc then x else acc )
let words = [ "F#" ; "ist" ; "cool" ]
let sentence =
words |> List.reduce (fun acc word -> acc + " " + word )
Wichtig : reduce nimmt das erste Element als Startwert. Darum funktioniert reduce nicht mit einer leeren Liste:[] |> List.reduce (fun acc x -> acc + x ) // Fehler
List.fold
List.fold ist ähnlich wie reduce, aber man gibt einen Startwert mit.
let numbers = [ 1 ; 2 ; 3 ; 4 ]
let total =
numbers |> List.fold (fun acc x -> acc + x ) 0
Unterschied zwischen reduce und fold
List.reduce nimmt das erste Listenelement als Startwert, während List.fold einen eigenen Startwert bekommt.[ 1 ; 2 ; 3 ] |> List.reduce (fun acc x -> acc + x ) // Startet mit 1
[ 1 ; 2 ; 3 ] |> List.fold (fun acc x -> acc + x ) 0 // Startet mit 0
Deshalb funktioniert fold auch mit leeren Listen im Gegensatz zu reduce, wo ein Fehler geworfen wird. [] |> List.fold (fun acc x -> acc + x ) 0
Nur fold kann z.B. aus einer int list einen string machen. let numbers = [ 1 ; 2 ; 3 ]
let text =
numbers |> List.fold (fun acc x -> acc + string x ) ""
List.foldBack
List.foldBack läuft von rechts nach links durch die Liste.
let numbers = [ 1 ; 2 ; 3 ]
let result =
List.foldBack (fun x acc -> acc + string x ) numbers ""
Kombination mehrerer Funktionen
In F# kombiniert man Listenfunktionen oft mit der Pipe |>.
// Gerade Zahlen verdoppeln und summieren
let numbers = [ 1 ; 2 ; 3 ; 4 ; 5 ; 6 ]
let result =
numbers
|> List.filter (fun x -> x % 2 = 0 )
|> List.map (fun x -> x * 2 )
|> List.sum
type Student = {
Name : string
Grade : float
}
let students = [
{ Name = "Anna" ; Grade = 5.5 }
{ Name = "Ben" ; Grade = 4.0 }
{ Name = "Carla" ; Grade = 3.5 }
{ Name = "Daniel" ; Grade = 6.0 }
]
// Alle bestandenen Schülernamen sortiert
let passedNames =
students
|> List.filter (fun student -> student.Grade >= 4.0 )
|> List.sortBy (fun student -> student.Name )
|> List.map (fun student -> student.Name )
xs = [2; 3]
{ Name = "Anna"; Grade = 5.5 }
{ Name = "Ben"; Grade = 4.0 }
]
{ Name = "Carla"; Grade = 3.5 }
{ Name = "Ben"; Grade = 4.0 }
{ Name = "Anna"; Grade = 5.5 }
]