Geschrieben von Reinder de Vries am Juli 12 2020 in App Development, Swift

 flatMap und CompactMap Erklärt in Swift

Swift verfügt über eine Reihe von Funktionen, die zum Transformieren von Sammlungen und Sequenzen nützlich sind. In diesem Tutorial besprechen wir map(_:), flatMap(_:) und compactMap(_:).

Hier ist, worauf wir uns konzentrieren werden:

  1. Wie map(_:) eine Sammlung oder Sequenz durch Anwenden eines Abschlusses transformiert
  2. Wie flatMap(_:) ein Eingabearray nach dem Aufruf von map(_:)
  3. reduzieren kann Wie compactMap(_:) nil aus dem Eingabearray entfernt

In einem früheren Tutorial haben wir besprochen, wie Sie filter(_:) und reduce(_:). Diese Funktionen höherer Ordnung sind sehr hilfreich, um Sammlungen auf prägnante und aufschlussreiche Weise zu transformieren.

Bereit? Lass uns gehen.

  1. Verwenden der Map-Funktion in Swift
  2. Verwenden der flatMap-Funktion
  3. Verwenden der CompactMap-Funktion
  4. Warum flatMap und CompactMap verwenden?
  5. Weiterführende Literatur

Noch nicht vertraut mit Verschlüssen oder Funktionen höherer Ordnung? Stellen Sie sicher, dass Sie sich zuerst über diese informieren:

  • Der ultimative Leitfaden für Verschlüsse in Swift
  • Karte, Reduzieren und Filtern in Swift

Mit der Map-Funktion in Swift

Als schnelle Auffrischung von Funktionen höherer Ordnung in Swift ist unser Ausgangspunkt die Funktion map(_:). Diese Funktion wendet eine Transformation auf jedes der Elemente in einer Sequenz an, z. B. ein Array oder ein Wörterbuch.

Hier ist ein Beispiel:

sei Zahlen =
sei Ergebnis = Zahlen.karte({ $0 * $0 })
drucken(Ergebnis)
Warnungen ausblenden

Lassen Sie uns das aufschlüsseln:

Zuerst erstellen wir ein Array numbers mit einigen ganzzahligen Werten. Dann wird die Funktion map(_:) auf numbers aufgerufen und ihr Ergebnis result zugewiesen.

Die Funktion map(_:) hat einen Parameter, einen Abschluss, der das Ergebnis von zurückgibt. Das entspricht dem ersten Parameter des Abschlusses, dh der Nummer von numbers, die transformiert wird.

Wir berechnen das Quadrat jeder Zahl in numbers. Im Wesentlichen wird die Operation für jede Zahl in numbers aufgerufen, und das resultierende Array wird result zugewiesen. Sie transformieren – oder „mappen“ – ein Array in ein anderes.

Die Transformation eines Arrays mit map(_:) ähnelt der Verwendung einer for-Schleife, ist jedoch viel prägnanter. Wie diese:

let numbers = var result = ()for number in numbers { result += }print(result)

Hier ist eine andere Art, es zu betrachten. Mit map(_:) wird das eingegebene Zahlenarray in ein anderes Zahlenarray umgewandelt. Wie diese:

2 => 2 * 2 => 43 => 3 * 3 => 94 => 4 * 4 => 165 => 5 * 5 => 25

Funktionen wie map(_:) werden als Funktionen höherer Ordnung bezeichnet, da sie im Gegensatz zu normalen Werten eine Funktion als Eingabe verwenden. Funktionen höherer Ordnung können auch Funktionen ausgeben, was für ein Programmierparadigma namens funktionale Programmierung nützlich ist.

Technisch gesehen können Sie Funktionen höherer Ordnung wie map(_:) für jede Sequenz aufrufen. Dazu gehören Sammlungen wie Arrays, Wörterbücher und Mengen, Bereiche wie 1...100 und sogenannte Iteratoren. Alles, was im Grunde wie eine „Liste“ von Werten aussieht.

Wir werden am Ende dieses Tutorials diskutieren, warum Funktionen höherer Ordnung nützlich sind. Lernen wir zuerst flatMap(_:) und compactMap(_:) kennen.

Als iOS-Entwickler eingestellt werden

Lernen Sie, iOS 14-Apps mit Swift 5 zu erstellen

Melden Sie sich für meinen iOS-Entwicklungskurs an und erfahren Sie, wie Sie Ihre Karriere als professioneller iOS-Entwickler beginnen können.

Mit der flatMap-Funktion

ähnelt die Funktion flatMap(_:) der Funktion map(_:), mit der Ausnahme, dass das resultierende Array „abgeflacht“ wird. Hier ein Beispiel:

sei Zahlen = , , ]
sei Ergebnis = Zahlen.flatMap({ $0 })
drucken(Ergebnis)
Warnungen ausblenden

Der obige Code beginnt mit einem verschachtelten Array von Ganzzahlen. Das Array numbers besteht aus einem Array von 3 Arrays, die jeweils 3 Zahlen enthalten.

Der Abschluss { } gibt einfach das erste Argument des Abschlusses zurück, dh die einzelnen verschachtelten Arrays. Es findet keine Transformation oder Operation statt. Wenn Sie jedoch flatMap(_:) im Array numbers anstelle von map(_:) aufrufen, erhalten Sie ein abgeflachtes Array einzelner Nummern. Im Gegensatz zum Eingabearray numbers enthält das Ergebnisarray keine verschachtelten Arrays!

Schauen wir uns ein anderes Beispiel an. Stellen Sie sich vor, Sie arbeiten mit 4 Gruppen von Giraffen und möchten eine einzelne Gruppe von Giraffen erstellen, die größer als eine bestimmte Höhe sind. Hier ist, wie Sie das tun:

lassen Sie Giraffen = , , ]
lassen Sie Giraffen = Giraffen.flatMap({ $0.filtern({ $0 > 10 }) })
drucken())
Warnungen ausblenden

Sehen Sie, wie giraffes ein Array von Arrays enthält? Im obigen Code wird die Funktion filter(_:) für jedes verschachtelte Array innerhalb von giraffes aufgerufen. Wir wollen nur ganze Zahlen (Giraffen!), die größer als 10 sind. Die resultierenden Arrays werden zu einem „flachen“ Array abgeflacht und tallest zugewiesen.

Überlegen Sie, was passieren würde, wenn wir map(_:) anstelle von flatMap(_:) verwendet hätten. Das resultierende Array würde nicht abgeflacht. Stattdessen wäre es das:

, , ]

Es ist wichtig zu beachten, dass die Funktion flatMap(_:) zuerst map(_:) für die Array-Elemente aufruft und diese dann reduziert. Deshalb funktioniert so etwas wie das Folgende nicht:

let numbers = , , ]let result = numbers.flatMap({  * 2 })

Im obigen Code bezieht sich auf die Arrays innerhalb von Zahlen. Das Multiplizieren eines Arrays mit zwei ist unmöglich, daher funktioniert dieser Code nicht.

Es ist klug, Flatmapping als ein Array in einer Dimension weniger zu betrachten. Sie beginnen mit einem zweidimensionalen Array und enden nach flatMap(_:) mit einem eindimensionalen Array.

Was ist mit der Verwendung von flatMap(_:) mit Optionals? Schauen wir uns das als nächstes an.

Der Name „compact Map“ basiert auf der Idee, dass das Entfernen von nil Elementen aus einem Array das Array kompakter macht. Ebenso kommt der Name „flache Karte“ von der Abflachung des Arrays. Und „Mapping“ ist ein Konzept aus der Mathematik, bei dem Sie die Werte in einer Menge mit einer anderen Menge verknüpfen.

Verwenden der CompactMap-Funktion

Die compactMap(_:) -Funktion entfernt nil -Werte aus dem Eingabearray. Es ist super nützlich, wenn Sie mit Optionals arbeiten.

Vor Swift 4.1 könnte die flatMap(_:) -Funktion (oben) auch verwendet werden, um nil -Werte aus abgeflachten Arrays herauszufiltern. Seit Swift 4.1+ verwenden Sie jetzt den expliziten compactMap(_:) für diesen Zweck.

Hier ist ein Beispiel:

sei Zahlen =
sei Ergebnis = Zahlen.compactMap({ Int($0) })
drucken(Ergebnis)
Warnungen ausblenden

Sehen Sie, was passiert? Der wichtigste Teil des Codes ist Int(). Dies nimmt eine einzelne Zeichenfolge von numbers mit und versucht, mit dem Initialisierer Int() in eine Ganzzahl zu konvertieren.

Dieser Int() Initialisierer ist fehlerhaft: Er kann nil – ein optionales – zurückgeben, daher ist sein Rückgabetyp Int? . Daher ist der Rückgabetyp der Zuordnungstransformation – ein Array optionaler Ganzzahlen.

Die Funktion compactMap(_:) entfernt automatisch nil Elemente aus dem zurückgegebenen Array, nachdem map(_:) aufgerufen wurde. Daher ist der Rückgabetyp nicht optional.

Im obigen Code ist der Typ von result . Wenn Sie map(_:) verwendet hätten, wäre der Rückgabetyp gewesen. Und Sie hätten einen zusätzlichen Schritt benötigt, um die Werte aus dem Array zu entpacken und mit ihnen zu arbeiten.

Warum flatMap und CompactMap verwenden?

Bevor wir uns mit den realen Anwendungsfällen von flatmap und compactmap befassen, wollen wir diese Funktionen höherer Ordnung und ihre Zwecke kurz zusammenfassen.

  1. Die Funktion map(_:) wendet einen Abschluss auf eine Eingabesammlung an und gibt die transformierte Sammlung zurück
  2. Die Funktion flatMap(_:) macht dasselbe und reduziert auch die resultierende Sammlung
  3. Die Funktion compactMap(_:) macht dasselbe wie map(_:) und entfernt auch nil aus der resultierenden Sammlung

Die Arbeit mit map(_:), flatMap(_:) und compactMap(_:) in der Zusammenfassung macht es manchmal schwierig, sich ihre praktischen Anwendungsfälle vorzustellen. Lassen Sie uns besprechen, warum Sie sie verwenden möchten.

Die Verwendung von Funktionen wie map(_:) zum Anwenden von Transformationen auf Sequenzen hat einige Vorteile:

  • Es ist prägnanter als die Verwendung einer for Schleife, da Sie keine temporären Variablen und einen mehrzeiligen for in { } Block benötigen.
  • Sie können normalerweise einen Aufruf an map(_:) in einer Zeile schreiben, wodurch Ihr Code (normalerweise) lesbarer wird.
  • Funktionen wie map(_:) können verkettet werden, sodass Sie mehrere Transformationen nacheinander auf eine Sequenz anwenden können.

Im Allgemeinen sind Funktionen höherer Ordnung nützlich, da Sie eine Funktion auf eine Folge von Werten anwenden können. Anstatt die Transformation prozedural zu codieren, können Sie die Funktion einfach anwenden und ein Ergebnis zurückerhalten.

Der praktischste Anwendungsfall für flatMap(_:) ist das Arbeiten mit Eingabewerten, die gruppiert oder verschachtelt sind, aber der gewünschte Ausgabewert muss eindimensional sein.

In einer Musik-App können Sie beispielsweise 3 Arrays haben: Titel, Interpreten und Wiedergabelisten. Sie kombinieren sie in einem Array, rufen flatMap(_:) auf, wählen die Titel, Interpreten und Wiedergabelisten aus, für die isFavorite true ist, und erhalten eine flache Liste der Elemente, die als Favoriten ausgewählt wurden.

Ein praktischer Anwendungsfall für compactMap(_:) ist die Arbeit mit einer Transformation, die nil zurückgeben kann. Sie sparen sich ein paar triviale Schritte, indem Sie compactMap(_:) nil -Werte sofort herausfiltern lassen. Ein zusätzlicher Vorteil ist der nicht optionale Rückgabetyp von compactMap(_:); Die Funktion filter(_:) hätte im Vergleich dazu einen optionalen Wert zurückgegeben, wenn Sie nil herausgefiltert hätten.

Sie können flatMap(_:) und compactMap(_:) und sogar filter(_:) oder reduce(_:_:) kombinieren. Stellen Sie sich vor, Sie erstellen eine Social-Media-App. Sie möchten eine Zeitleiste mit Beiträgen für einen Benutzer erstellen. Sie verwenden 3 Abfragen, um Post-IDs für den Benutzer auszuwählen, z. B. aus Follower-Posts, Anzeigen und Trendthemen.

  • Sie können map(_:) verwenden, um diese IDs zu tatsächlichen Post Objekten zu erweitern
  • Sie können flatMap(_:) verwenden, um die 3 Gruppen zu einer Sammlung zusammenzufassen
  • Sie können compactMap(_:) verwenden, um Beiträge zu verwerfen, die nicht erweitert werden konnten

Ordentlich!

Als iOS-Entwickler eingestellt werden

Lernen Sie, iOS 14-Apps mit Swift 5 zu erstellen

Melden Sie sich für meinen iOS-Entwicklungskurs an und erfahren Sie, wie Sie Ihre Karriere als professioneller iOS-Entwickler beginnen können.

Weiterführende Literatur

Es lohnt sich, map(_:), flatMap(_:) und compactMap(_:) kennenzulernen, da sie Ihren Code prägnanter und lesbarer machen. Sie können dem Code Ihrer App mehr funktionale Programmierung hinzufügen. Sobald Sie sich an sie gewöhnt haben, können Sie nicht glauben, dass Sie Ihre Arbeit ohne sie erledigen könnten.

Besonders hervorzuheben sind die Unterschiede zwischen map(_:), flatMap(_:) und compactMap(_:). Die erste wendet eine Transformation auf eine Sequenz an, die zweite reduziert das resultierende Array und die dritte entfernt nil -Werte, bevor das Ergebnis zurückgegeben wird. Großartig!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.