skriven av Reinder de Vries den 12 juli 2020 i App Development, Swift

FlatMap och CompactMap förklaras i Swift

Swift har en massa funktioner som är användbara för att omvandla samlingar och sekvenser. I denna handledning diskuterar vi map(_:), flatMap(_:) och compactMap(_:).

här är vad vi ska fokusera på:

  1. hur map(_:) omvandlar en samling eller sekvens genom att tillämpa en stängning till den
  2. hur flatMap(_:) kan platta en ingångsmatris, efter att ha ringt map(_:)
  3. hur compactMap(_:) tar bort nil från ingångsmatrisen

i en tidigare handledning har vi diskuterat hur du kan använda filter(_:) och reduce(_:). Dessa högre ordningsfunktioner är mycket användbara för att omvandla Samlingar, på ett kortfattat och insiktsfullt sätt.

redo? Nu går vi.

  1. använda kartfunktionen i Swift
  2. använda FlatMap-funktionen
  3. använda CompactMap-funktionen
  4. Varför använda FlatMap och CompactMap?
  5. Vidare läsning

ännu inte bekant med stängningar eller funktioner med högre ordning? Se till att läsa upp de första:

  • den ultimata guiden till nedläggningar i Swift
  • karta, minska och filtrera i Swift

med hjälp av kartfunktionen i Swift

som en snabb uppdatering på högre ordningsfunktioner i Swift är vår utgångspunkt funktionen map(_:). Denna funktion tillämpar en omvandling till vart och ett av elementen i en sekvens, som en matris eller ordbok.

här är ett exempel:

låt siffror =
låt resultat = siffror.karta({ $0 * $0 })
Skriv ut (resultat)
dölj varningar

Låt oss bryta ner det:

först skapar vi en array numbers med några heltalvärden. Sedan anropas funktionen map(_:)numbersoch dess resultat tilldelas result.

funktionen map(_:) har en parameter, en stängning, som returnerar resultatet av . motsvarar den första parametern för Stängningen, dvs numret från numbers som transformeras.

vi beräknar kvadraten för varje tal i numbers. I huvudsak kallas operationen på varje nummer i numbers, och den resulterande matrisen tilldelas result. Du omvandlar – eller” kartlägger ” – en array till en annan.

att omvandla en array med map(_:) liknar att använda en for-loop, men mycket mer kortfattad. Så här:

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

här är ett annat sätt att titta på det. Med map(_:) omvandlas ingångsmatrisen av siffror till en annan uppsättning siffror. Så här:

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

funktioner som map(_:) kallas högre ordningsfunktioner, eftersom de tar en funktion som inmatning i motsats till vanliga värden. Funktioner med högre ordning kan också mata ut funktioner, vilket är användbart för ett programmeringsparadigm som kallas funktionell programmering.

Tekniskt kan du ringa högre ordningsfunktioner som map(_:) på vilken sekvens som helst. Detta inkluderar samlingar som matriser, ordböcker och uppsättningar, intervall som 1...100 och så kallade iteratorer. Allt som ser ut som en ”lista” av värden, i grund och botten.

vi diskuterar varför högre ordningsfunktioner är användbara i slutet av denna handledning. Låt oss först gå vidare för att lära oss om flatMap(_:) och compactMap(_:).

bli anställd som IOS-utvecklare

lär dig att bygga iOS 14-appar med Swift 5

registrera dig för min iOS-utvecklingskurs och lär dig hur du startar din karriär som professionell iOS-utvecklare.

använda FlatMap-funktionen

funktionen flatMap(_:) liknar map(_:) förutom att den ”plattar” den resulterande matrisen. Här är ett exempel:

låt siffror =,,]
låt resultat = siffror.flatMap ({$0 })
Skriv ut (resultat)
dölj varningar

ovanstående kod börjar med en kapslad uppsättning heltal. Arrayen numbers består av en array med 3 arrayer, som var och en innehåller 3 siffror.

Stängningen { } returnerar helt enkelt det första argumentet för Stängningen, dvs de enskilda kapslade matriserna. Ingen omvandling eller operation sker. När du ringer flatMap(_:)numbers – arrayen, istället för map(_:), hamnar du med en platt uppsättning enskilda nummer. Till skillnad från ingångsmatrisen numbers innehåller resultatmatrisen inte kapslade matriser!

Låt oss titta på ett annat exempel. Tänk dig att du arbetar med 4 grupper av giraffer, och vill skapa en enda grupp av giraffer som är högre än en viss höjd. Så här gör du det:

låt giraffer =,,]
låt högsta = giraffer.flatMap ({$0 .filter({ $0 > 10 }) })
Skriv ut (högsta)
dölj varningar

se hur giraffes innehåller en rad arrayer? I ovanstående kod anropas funktionen filter(_:)på varje kapslad array inuti giraffes. Vi vill bara heltal (giraffer!) som är större än 10. De resulterande arraysna plattas i en” platt ” array och tilldelas tallest.

Tänk på vad som skulle hända om vi hade använt map(_:)istället för flatMap(_:). Den resulterande matrisen skulle inte plattas ut. Istället, det skulle vara detta:

, , ]

det är viktigt att notera att funktionen flatMap(_:) anropar map(_:) på arrayobjekten först och plattar sedan ut den. Det är därför något som följande inte fungerar:

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

i ovanstående kod hänvisar till arraysna inuti siffror. Att multiplicera en array med två är omöjligt, så det är därför den här koden inte fungerar.

det är smart att tänka på flatmapping som att se en array i en mindre dimension. Du börjar med en tvådimensionell array och slutar med en endimensionell array efter flatMap(_:).

vad sägs om att använda flatMap(_:) med alternativ? Låt oss titta på det nästa.

namnet ”kompakt karta” bygger på tanken att ta bort nil objekt från en array gör arrayen mer kompakt. På samma sätt kommer namnet ”platt karta” från att platta matrisen. Och” kartläggning ” är ett begrepp från matematik, där du associerar värdena i en uppsättning med en annan uppsättning.

använda CompactMap-funktionen

funktionen compactMap(_:) tar bort nil värden från ingångsmatrisen. Det är super användbart när du arbetar med alternativ.

Före Swift 4.1, funktionen flatMap(_:) (ovan) kan också användas för att filtrera bort nil värden från platta arrayer. Sedan Swift 4.1 + använder du nu explicit compactMap(_:) för detta ändamål.

här är ett exempel:

låt siffror =
låt resultat = siffror.compactMap ({int ($0)})
Skriv ut (resultat)
dölj varningar

se vad som händer? Den viktigaste delen av koden är Int(). Detta tar en enskild sträng från numbers med och försöker konvertera till ett heltal med Int() initialiseraren.

denna Int() initializer är failable: den kan returnera nil – en valfri – så dess returtyp är Int?. Som ett resultat är returtypen för kartläggningstransformationen – en rad valfria heltal.

funktionen compactMap(_:) tar automatiskt bort nil – element från den returnerade arrayen efter att ha ringt map(_:) på den. Som sådan är returtypen icke-valfri.

i ovanstående kod är typen result . Om du skulle ha använt map(_:) skulle returtypen ha varit . Och du skulle ha behövt ett extra steg för att packa upp värdena från matrisen, för att arbeta med dem.

Varför använda FlatMap och CompactMap?

innan vi diskuterar de verkliga användningsfallen av flatmap och compactmap, låt oss göra en snabb sammanfattning av dessa högre ordningsfunktioner och deras syften.

  1. funktionenmap(_:) tillämpar en stängning på en inmatningssamling och returnerar den transformerade samlingen
  2. funktionenflatMap(_:) gör samma sak, och den plattar också den resulterande samlingen
  3. funktionen compactMap(_:) gör samma sak som map(_:), och den tar också bortnil från den resulterande samlingen

arbeta med map(_:), flatMap(_:) och compactMap(_:) i abstrakt gör det ibland svårt att föreställa sig deras praktiska användningsfall. Låt oss diskutera varför du vill använda dem.

att använda funktioner som map (_:) för att tillämpa transformationer på sekvenser har några fördelar:

  • det är mer kortfattat än att använda en for-slinga, eftersom du inte behöver tillfälliga variabler och ett flerradigt for in { } – block.
  • du kan vanligtvis skriva ett samtal till map(_:) på en rad, vilket (vanligtvis) gör din kod mer läsbar.
  • funktioner som map(_:) kan kedjas, så du kan tillämpa flera transformationer till en sekvens en efter en.

i allmänhet är högre ordningsfunktioner användbara eftersom de låter dig tillämpa en funktion på en sekvens av värden. Istället för att koda transformationen procedurellt kan du bara använda funktionen och få ett resultat tillbaka.

det mest praktiska användningsfallet för flatMap(_:) arbetar med ingångsvärden som är grupperade eller kapslade, men det utgångsvärde du vill ha måste vara endimensionellt.

du kan till exempel i en musikapp ha 3 matriser: låtar, artister och spellistor. Du kombinerar dem i en array, Ring flatMap(_:) på den, välj låtar, artister och spellistor för vilka isFavorite är true och sluta med en platt lista över objekt som har favoriserats.

ett praktiskt användningsfall för compactMap(_:) arbetar med en transformation som kan returnera nil. Du sparar dig några triviala steg genom att låta compactMap(_:) filtrera bort nil värden omedelbart. En extra fördel är compactMap(_:): s icke-valfria returtyp; funktionen filter(_:)skulle i jämförelse ha returnerat ett valfritt värde om du filtrerade bort nil.

du kan kombinera flatMap(_:) och compactMap(_:), och till och med filter(_:)eller reduce(_:_:). Tänk dig att du bygger en app för sociala medier. Du vill skapa en tidslinje för inlägg för en användare. Du använder 3 frågor för att välja post-ID för användaren, till exempel från följare inlägg, annonser och trender ämnen.

  • du kan använda map(_:) för att expandera dessa ID till faktiska Post objekt
  • du kan använda flatMap(_:) för att platta de 3 grupperna i en samling
  • du kan använda compactMap(_:) för att kasta inlägg som inte kunde utökas

snyggt!

bli anställd som IOS-utvecklare

lär dig att bygga iOS 14-appar med Swift 5

registrera dig för min iOS-utvecklingskurs och lär dig hur du startar din karriär som professionell iOS-utvecklare.

Vidare läsning

det är värt att lära sig om map(_:), flatMap(_:) och compactMap(_:), eftersom de gör din kod mer kortfattad och läsbar. Du kan lägga till mer funktionell programmering i appens kod. När du väl är van vid dem kan du inte tro att du kan göra ditt arbete utan dem.

speciellt skillnaderna mellan map(_:), flatMap(_:) och compactMap(_:) är värda att påpeka. Den första tillämpar en transformation till en sekvens, den andra plattar den resulterande matrisen och den tredje tar bort nil värden innan den returnerar resultatet. Häftig!

Lämna ett svar

Din e-postadress kommer inte publiceras.