skrevet af Reinder de Vries den 12. juli 2020 i appudvikling, hurtig

FlatMap og CompactMap forklaret i hurtig

Hurtig har en masse funktioner, der er nyttige til at transformere samlinger og sekvenser. I denne tutorial vil vi diskutere map(_:), flatMap(_:) og compactMap(_:).

her er hvad vi vil fokusere på:

  1. hvordan map(_:) transformerer en samling eller sekvens ved at anvende en lukning på den
  2. hvordan flatMap(_:) kan flade et inputarray efter at have ringet map(_:)
  3. hvordan compactMap(_:) fjerner nil fra inputarrayet

i en tidligere tutorial har vi diskuteret, hvordan du kan bruge

klar? Lad os gå.

  1. brug af kortfunktionen i hurtig
  2. brug af FlatMap-funktionen
  3. brug af CompactMap-funktionen
  4. Hvorfor bruge FlatMap og CompactMap?
  5. yderligere læsning

endnu ikke bekendt med lukninger eller højere ordensfunktioner? Sørg for at læse op på dem først:

  • den ultimative guide til lukninger i hurtig
  • Kortlæg, reducer og filtrer hurtigt

brug af kortfunktionen i hurtig

som en hurtig genopfriskning af højere ordensfunktioner i Hurtig, vores udgangspunkt er map(_:) -funktionen. Denne funktion anvender en transformation til hvert af elementerne i en sekvens, som et array eller ordbog.

her er et eksempel:

lad tal =
lad resultat = tal.kort({ $0 * $0 })
Udskriv (resultat)
Skjul advarsler

lad os nedbryde det:

først opretter vi et array numbers med et par heltalværdier. Derefter kaldes funktionen map(_:) numbers, og dens resultat er tildelt result.

funktionen map(_:) har en parameter, en lukning, som returnerer resultatet af . svarer til den første parameter for lukningen, dvs.tallet fra numbers, der transformeres.

vi beregner kvadratet af hvert tal i numbers. I det væsentlige kaldes operationen på hvert nummer i numbers, og det resulterende array er tildelt result. Du omdanner – eller” kortlægger ” – et array til et andet.

omdannelse af et array med map(_:) svarer til at bruge en for loop, men meget mere kortfattet. Sådan her:

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

her er en anden måde at se på det. Med map(_:) omdannes input array af tal til en anden række tal. Sådan her:

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

funktioner som map(_:) kaldes højere ordensfunktioner, fordi de tager en funktion som input i modsætning til almindelige værdier. Funktioner med højere orden kan også udsende funktioner, hvilket er nyttigt til et programmeringsparadigme kaldet funktionel programmering.

teknisk set kan du ringe til højere ordensfunktioner som map(_:) på en hvilken som helst sekvens. Dette omfatter samlinger som arrays, ordbøger og sæt, områder som 1...100 og såkaldte iteratorer. Alt, hvad der ligner en” liste ” over værdier, dybest set.

vi vil diskutere, hvorfor højere ordensfunktioner er nyttige i slutningen af denne vejledning. Lad os først gå videre for at lære om flatMap(_:) og compactMap(_:).

bliv ansat som iOS-udvikler

Lær at bygge iOS 14-apps med hurtig 5

Tilmeld dig mit iOS-udviklingskursus, og lær, hvordan du starter din karriere som professionel iOS-udvikler.

brug af FlatMap-funktionen

funktionen flatMap(_:) svarer til map(_:) bortset fra at den “flader” det resulterende array. Her er et eksempel:

lad tal =,,]
lad resultat = tal.flatMap ({$0})
Udskriv (resultat)
Skjul advarsler

ovenstående kode starter med en indlejret række heltal. numbers arrayet består af et array af 3 arrays, som hver indeholder 3 tal.

lukningen { } returnerer simpelthen det første argument for lukningen, dvs.de individuelle indlejrede arrays. Der sker ingen transformation eller operation. Når du ringer flatMap(_:)numbers arrayet, i stedet for map(_:), ender du med et fladt udvalg af individuelle numre. I modsætning til input array numbers indeholder resultat array ikke indlejrede arrays!

lad os se på et andet eksempel. Forestil dig, at du arbejder med 4 grupper af giraffer, og ønsker at oprette en enkelt gruppe giraffer, der er højere end en bestemt højde. Sådan gør du det:

lad giraffer =,,]
lad højeste = giraffer.flatMap ({ $0.filter({ $0 > 10 }) })
print (højeste)
Skjul advarsler

se hvordan giraffes indeholder en række arrays? I ovenstående kode kaldes funktionen filter(_:)på hvert indlejret array inde giraffes. Vi vil kun have heltal (giraffer!) der er større end 10. De resulterende arrays er fladt i et” fladt ” array og tildelt tallest.

overvej hvad der ville ske, hvis vi havde brugt map(_:) i stedet for flatMap(_:). Det resulterende array ville ikke blive fladt. I stedet, det ville være dette:

, , ]

det er vigtigt at bemærke, at funktionen flatMap(_:) kalder map(_:) på array-elementerne først og derefter flader den. Derfor fungerer noget som følgende ikke:

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

i ovenstående kode henviser til arrays inde i tal. Det er umuligt at multiplicere et array med to, så det er derfor, denne kode ikke fungerer.

det er smart at tænke på flatmapping som at se et array i en mindre dimension. Du starter med et todimensionelt array og ender med et endimensionelt array efter flatMap(_:).

hvad med at bruge flatMap(_:) med optionals? Lad os se på det næste.

navnet “compact map” er baseret på ideen om at fjerne nil elementer fra et array gør arrayet mere kompakt. Ligeledes kommer navnet” fladt kort ” fra udfladning af arrayet. Og” kortlægning ” er et koncept fra matematik, hvor du forbinder værdierne i et sæt med et andet sæt.

brug af CompactMap-funktionen

funktionen compactMap(_:) fjerner nil værdier fra inputarrayet. Det er super nyttigt, når du arbejder med optionals.

Før Hurtig 4.1, flatMap(_:) funktionen (ovenfor) kunne også bruges til at filtrere nil værdier fra fladede arrays. Siden hurtig 4.1 + bruger du nu den eksplicitte compactMap(_:) til dette formål.

her er et eksempel:

lad tal =
lad resultat = tal.compactMap ({Int ($0)})
Udskriv (resultat)
Skjul advarsler

se hvad sker der? Den vigtigste del af koden er Int(). Dette tager en individuel streng fra numbers med og forsøger at konvertere til et heltal med initialiseringen Int().

denne Int() initialisering kan mislykkes: den kan returnere nil – en valgfri – så dens returtype er Int?. Som følge heraf er returtypen af kortlægningstransformationen – en række valgfrie heltal.

funktionen compactMap(_:) fjerner automatisk nil elementer fra det returnerede array efter at have ringet map(_:) på det. Som sådan er det returtype er ikke-valgfri.

i ovenstående kode er typen af result. Hvis du ville have brugt map(_:), ville returtypen have været . Og du ville have brug for et ekstra skridt til at pakke værdierne ud af arrayet for at arbejde med dem.

Hvorfor bruge FlatMap og CompactMap?

før vi diskuterer de virkelige brugssager af flatmap og compactmap, lad os lave en hurtig oversigt over disse højere ordensfunktioner og deres formål.

  1. funktionen map(_:) anvender en lukning på en inputsamling og returnerer den transformerede samling
  2. funktionen flatMap(_:) gør det samme, og den flader også den resulterende samling
  3. funktionen compactMap(_:) gør det samme som map(_:), og den fjerner også nil fra den resulterende samling

at arbejde med map(_:), flatMap(_:) og compactMap(_:) abstrakt gør det nogle gange svært at forestille sig deres praktiske brugssager. Lad os diskutere, hvorfor du vil bruge dem.

brug af funktioner som map (_:) til at anvende transformationer på sekvenser har et par fordele:

  • det er mere kortfattet end at bruge en for loop, fordi du ikke har brug for midlertidige variabler og en multi-line for in { } blok.
  • du kan typisk skrive et opkald til map(_:) på en linje, hvilket (normalt) gør din kode mere læsbar.
  • funktioner som map(_:) kan kædes, så du kan anvende flere transformationer til en sekvens en efter en.

generelt er højere ordensfunktioner nyttige, fordi de giver dig mulighed for at anvende en funktion på en række værdier. I stedet for at kode transformationen proceduremæssigt, kan du bare anvende funktionen og få et resultat tilbage.

den mest praktiske brugssag for flatMap(_:) arbejder med inputværdier, der er grupperet eller indlejret, men den ønskede outputværdi skal være endimensionel.

du kan f.eks. i en musikapp have 3 arrays: sange, kunstnere og afspilningslister. Du kombinerer dem i et array, kalder flatMap(_:) på det, Vælg de sange, kunstnere og afspilningslister, som isFavorite er true, og ender med en flad liste over emner, der er blevet foretrukket.

en praktisk brugssag til compactMap(_:)arbejder med en transformation, der kan vende tilbage nil. Du sparer dig selv et par trivielle trin ved at lade compactMap(_:) filtrere nil værdier straks. En ekstra fordel er compactMap(_:) ‘ s ikke-valgfri returtype; funktionen filter(_:)ville til sammenligning have returneret en valgfri værdi, hvis du filtrerede nil.

du kan kombinere flatMap(_:) og compactMap(_:)og endda filter(_:) eller reduce(_:_:). Forestil dig, at du bygger en app til sociale medier. Du vil konstruere en tidslinje for indlæg til en bruger. Du bruger 3 forespørgsler til at vælge post-id ‘ er til brugeren, for eksempel fra tilhængerindlæg, reklamer og populære emner.

  • du kan bruge map(_:) til at udvide disse id ‘ er til faktiske Post objekter
  • du kan bruge flatMap(_:) til at flade de 3 grupper i en samling
  • du kan bruge compactMap(_:) til at kassere indlæg, der ikke kunne udvides

Neat!

bliv ansat som iOS-udvikler

Lær at bygge iOS 14-apps med hurtig 5

Tilmeld dig mit iOS-udviklingskursus, og lær, hvordan du starter din karriere som professionel iOS-udvikler.

yderligere læsning

det er værd at lære om map(_:), flatMap(_:) og compactMap(_:), fordi de gør din kode mere kortfattet og læsbar. Du kan tilføje mere funktionel programmering til din apps kode. Når du først er vant til dem, kan du ikke tro, at du kunne gøre dit arbejde uden dem.

især forskellene mellem map(_:), flatMap(_:) og compactMap(_:) er værd at påpege. Den første anvender en transformation til en sekvens, den anden flader det resulterende array, og den tredje fjerner nil værdier, før resultatet returneres. Fedt!

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.