Operationen auf Listen ausführen

Abgeschlossen

Wenn Sie in einer Liste viele Elemente gespeichert haben, führen Sie Vorgänge häufig entweder für die gesamte Liste oder für einen Teil der Liste aus. Das Listenmodul enthält genau hierfür zahlreiche nützliche Vorgänge.

Funktionen des Listenmoduls

Neben den Eigenschaften gibt es ein Listenmodul mit Funktionen, die für eine Liste ausgeführt werden können. Mit den Funktionen werden häufig verwendete Vorgänge ausgeführt, wie z. B. Suchen, Filtern, Sortieren, Ausführen mathematischer Operationen usw.

Wiederholung

Bei einer Iteration wird jedes Element einer Liste von einem Anfangs- bis zu einem Endpunkt durchlaufen. Für Iterationen sind zwei Funktionen besonders nützlich:

  • iter(): Mit dieser Funktion können Sie über jedes Element in einer Liste iterieren, wie hier gezeigt:

    let cards = [ 1 .. 5 ]
    List.iter(fun i -> printfn "%i" i) cards // 1 2 3 4 5
    

    Die Funktion iter() akzeptiert eine Funktion. Im vorherigen Code stellen Sie eine anonyme Funktion mithilfe des Schlüsselworts fun bereit. Diese Funktion akzeptiert einen Parameter, der das aktuelle Element während des Durchlaufs darstellt. Der folgende Code ist das Äquivalent dazu, den folgenden Code mit einer Schleife zu schreiben:

    for i in cards do printfn "%i" i
    
  • map(): Diese Funktion ähnelt iter(), ermöglicht Ihnen jedoch, das Vorhandene zu transformieren. Hier sehen Sie ein Beispiel:

    type Person = { FirstName: string; LastName: string  }
    let people = [
       { FirstName="Albert"; LastName= "Einstein" }
       { FirstName="Marie"; LastName="Curie" }
    ]
    let nobelPrizeWinners = List.map (fun person -> person.FirstName + person.LastName) people 
    printfn "%A" nobelPrizeWinners // ["Albert Einstein"; "Marie Curie"]
    

    Im vorherigen Code wird die Liste von Person-Objekten in eine Liste von Zeichenfolgen transformiert.

Filtern

Auch die Funktion filter() akzeptiert eine Funktion als Parameter, ihr Zweck besteht jedoch darin, die Elemente zu definieren, die beibehalten werden sollen. Ergibt der Ausdruck true, wird das Element beibehalten. Ergibt der Ausdruck false, wird das Element nicht in der gefilterten Liste angezeigt. Im folgenden Beispiel wird eine Liste so gefiltert, dass nur Elemente, deren Wert durch zwei teilbar ist, beibehalten werden:

let cards = [ 1 .. 5 ]
let filteredList = List.filter(fun i-> i % 2 = 0) cards
List.iter(fun i -> printfn "item %i" i) filteredList // item 2 item 4

Die Liste filteredList enthält jetzt nur die Elemente, die nach der Auswertung durch true den Wert i % 2 = 0 zurückgeben (das sind 2 und 4).

Sortieren

Das Sortieren einer Liste ist eine häufig durchgeführte Aktion. Die folgenden drei Funktionen können für das Sortieren von Listen nützlich sein:

  • sort() sortiert in aufsteigender Reihenfolge. Hier sehen Sie ein Beispiel:

    let list = [2; 1; 5; 3]
    let sortedList = List.sort list // 1 2 3 5 
    
  • sortBy(): Mit dieser Funktion wird auf einen Schlüssel verwiesen, nach dem sortiert werden soll. Angenommen, Sie verfügen über eine Liste von Personen, und jeder Eintrag weist die Felder name und age auf. Hier können Sie beispielsweise nach age sortieren. Diese Funktion nimmt eine Funktion an, in der Sie auf den Schlüssel verweisen. Ein weiterer Schlüssel kann die Länge einer Zeichenfolge sein, wie in dem folgenden Beispiel:

    let fruits = ["Banana"; "Apple"; "Pineapple"]
    let sortedFruits = List.sortBy (fun (fruit : string) -> fruit.Length) fruits // Apple, Banana, Pineapple
    
  • sortWith(): Mit dieser Funktion können Sie eine Vergleichsfunktion bereitstellen, da möglicherweise nicht sofort ersichtlich ist, welches der Elemente zuerst sortiert werden sollte. Der folgende Code enthält ein Beispiel hierzu:

    // assume a type like so
    type MagicCreature = { Name : string; Level: int; Attack: int }
    let creatures = [
       { Name="Dragon"; Level=2; Attack=20 }
       { Name="Orc"; Level=1; Attack=5 }
       { Name="Demon"; Level=2; Attack=10 } 
    ]
    
    // comparison function, -1 = less than, 1 = larger than, 0 = equal
    let compareCreatures c1 c2 =
         if c1.Level < c2.Level then -1
         else if c1.Level > c2.Level then 1
         else if c1.Attack < c2.Attack then -1
         else if c1.Attack > c2.Attack then 1
         else 0
    
    let sorted = List.sortWith compareCreatures creatures // { Name="Orc"; Level=1; Attack=5 }, { Name="Demon"; Level=2; Attack=10 }, { Name="Dragon"; Level=2; Attack=20 }
    

    Die vorherige Vergleichsfunktion compareCreatures() versucht zunächst, nach Level zu vergleichen. Bei gleicher Ebene versucht sie, nach Attack zu vergleichen. Bei einem Rückgabewert von -1 ist der Wert kleiner, bei 1 größer und bei 0gleich groß.

Eine weitere Möglichkeit besteht darin, ein bestimmtes Element zu suchen. Die folgenden Funktionen stehen hierfür zur Auswahl:

  • find(): Diese Funktion sucht das erste Element, das eine bestimmte Bedingung erfüllt. Für die Nutzung von find() müssen Sie auch eine Funktion (Prädikat) bereitstellen, die ausdrückt, wie das Element gesucht werden soll. Hier sehen Sie ein Beispiel:

    let list = [1; 2; 3; 4]
    let found = List.find( fun x -> x % 2 = 0) list // 2 - Only the first element that matches the condition is returned.
    
  • tryFind(). Diese Funktion nimmt eine Funktion (Prädikat), die angibt, wie der Wert gefunden wird, und eine Liste, in der gesucht werden soll. Sie gibt eine Option zurück. Hier sehen Sie ein Beispiel zur Verwendung:

    let findValue aValue aList =
         let found = aList |> List.tryFind(fun item -> item = aValue)
    
         match found with
         | Some value -> printfn "%i" value
         | None -> printfn "Not found"
    
    findValue 1 list // 1
    findValue 5 list // Not found
    

    Im vorherigen Code senden Sie einen Wert, der mit der Liste verglichen werden soll. Wenn er gefunden wird, gibt er Some zurück. Wird der Wert nicht gefunden, lautet die Rückgabe None.

  • tryFindIndex(). Wie bei tryFind() gibt diese Funktion eine Option zurück und akzeptiert eine Funktion (Prädikat), die einen booleschen Wert ergibt. Der Code könnte etwa folgendermaßen aussehen:

    let found = List.tryFindIndex(fun x -> x = 4) list
    match found with
       | Some index -> printfn "%i" index
       | None -> printfn "Not found"
    

Arithmetische Operationen

In manchen Situationen kann es nützlich sein, für eine Liste mathematische Operationen auszuführen. Die folgenden drei Funktionen sind von den zahlreichen Funktionen, die in der Listen-API zur Verfügung stehen, am nützlichsten:

  • sum(): Mit dieser Funktion durchlaufen Sie jedes Element, um alle Werte in der Liste zu summieren. Hier sehen Sie ein Beispiel zur Verwendung:

    let sum = List.sum [1 .. 5] // sum = 15 
    
  • sumBy(): Mit dieser Funktion geben Sie an, wie die Werte summiert werden sollen. Eine Möglichkeit besteht darin, auf die Felder zu verweisen, die summiert werden sollen:

    type OrderItem = { Name: string; Cost:int }
    
    let orderItems = [
           { Name="XBox"; Cost=500 }
           { Name="Book"; Cost=10 }
           { Name="Movie ticket"; Cost=7 }
         ]
    
    let sum = List.sumBy(fun item -> item.Cost) orderItems
    printfn "%i" sum // 517
    

    Im vorherigen Code wird auf das Feld Cost verwiesen, wodurch jedes Element in diesem Feld der Summe hinzugefügt wird.

  • average(): Diese Funktion ähnelt sum() darin, dass sie mit einer Liste von Zahlen arbeitet. Doch es gibt zwei Unterschiede:

    • Sie erwartet als Daten Gleitkommazahlen, keine ganzen Zahlen.
    • Sie berechnet einen Durchschnittswert, keine Summe.

    Hier sehen Sie ein Beispiel:

    let numbers = [ 1.0; 2.5; 3.0 ]
    let avg = List.average numbers
    printfn "%f" avg // 2.166667
    
  • averageBy(): Wie bei sumBy() akzeptiert averageBy() eine Funktion, in der Sie den gewünschten Wert angeben. Hier sehen Sie ein Beispiel:

    type WeatherMeasurement = { Date: string; Temperature: float }
    let measurements = [
        { Date="07/20/2021"; Temperature=21.3 }
        { Date="07/21/2021"; Temperature=23.2 }
        { Date="07/22/2021"; Temperature=20.7 }
    ]
    
    let avgBy = List.averageBy(fun m -> m.Temperature) measurements
    printfn "%f" avgBy // 21.733333