geschreven door Reinder de Vries op 12 juli 2020 In App Development, Swift

FlatMap en CompactMap uitgelegd in Swift

Swift heeft een aantal functies die nuttig zijn voor het transformeren van collecties en reeksen. In deze tutorial zullen we map(_:), flatMap(_:) en compactMap(_:)bespreken.

hier zullen we ons op richten:

  1. hoe map(_:) een verzameling of reeks transformeert door er een afsluiting op toe te passen
  2. hoe flatMap(_:) een invoerarray plat kan maken, na het aanroepen van map(_:)
  3. hoe compactMap(_:) nil verwijdert uit de invoerarray

in een vorige tutorial hebben we besproken hoe u filter(_:) en reduce(_:)kunt gebruiken. Deze hogere-orde functies zijn super nuttig voor het transformeren van collecties, op een beknopte en inzichtelijke manier.

klaar? Laten we gaan.

  1. de functie kaart gebruiken in Swift
  2. de functie FlatMap
  3. de functie CompactMap
  4. waarom FlatMap en CompactMap gebruiken?
  5. verder lezen

nog niet bekend met sluitingen of hogere functies? Zorg ervoor om te lezen op die eerste:

  • De Ultieme Gids Voor sluitingen in Swift
  • kaart, verminderen en filteren in Swift

met behulp van de kaart functie in Swift

als een snelle refresher op hogere-orde functies in Swift, ons uitgangspunt is de functie map(_:). Deze functie past een transformatie toe op elk van de elementen in een reeks, zoals een array of woordenboek.

hier is een voorbeeld:

laat getallen =
laat resultaat = getallen.kaart({ $0 * $0 })
afdrukken (resultaat)
Verberg waarschuwingen

laten we dat opsplitsen:

eerst maken we een array numbers met een paar integer waarden. Vervolgens wordt de functie map(_:) aangeroepen op numbers en het resultaat wordt toegewezen aan result.

de functie map(_:) heeft één parameter, een closure, die het resultaat van geeft. komt overeen met de eerste parameter van de afsluiting, d.w.z. het getal van numbers dat wordt getransformeerd.

we berekenen het kwadraat van elk getal in numbers. In essentie wordt de operatie op elk getal in numbers aangeroepen en wordt de resulterende array toegewezen aan result. Je transformeert – of” mapping ” – een array in een andere.

het transformeren van een array met map(_:) is vergelijkbaar met het gebruik van een for-lus, maar veel beknopter. Zoals dit:

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

hier is een andere manier om het te bekijken. Met map(_:) wordt de invoerarray van getallen omgezet in een andere array van getallen. Zoals dit:

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

functies zoals map(_:) worden hogere-orde functies genoemd, omdat ze een functie als input nemen in tegenstelling tot gewone waarden. Hogere-ordefuncties kunnen ook functies uitvoeren, wat nuttig is voor een programmeerparadigma genaamd functioneel programmeren.

technisch gezien kunt u functies met een hogere orde, zoals map(_:), aanroepen in elke reeks. Dit omvat verzamelingen zoals arrays, woordenboeken en sets, bereiken zoals 1...100 en zogenaamde iterators. Alles wat eruit ziet als een “lijst” van waarden, in principe.

we zullen bespreken waarom hogere-orde functies nuttig zijn aan het einde van deze tutorial. Laten we eerst verder gaan om meer te weten te komen over flatMap(_:) en compactMap(_:).

word aangenomen als iOS-ontwikkelaar

leer iOS-apps bouwen met Swift 5

meld je aan voor mijn iOS-ontwikkelcursus en leer hoe je je carrière als professionele iOS-ontwikkelaar kunt beginnen.

het gebruik van de FlatMap-functie

de flatMap(_:) – functie is vergelijkbaar met map(_:), behalve dat het de resulterende array” afvlakt”. Hier is een voorbeeld:

let numbers=,,]
let result = numbers.flatMap ({$0 })
print (resultaat)
waarschuwingen verbergen

de bovenstaande code begint met een geneste array van gehele getallen. De numbers array bestaat uit een array van 3 arrays, die elk 3 getallen bevatten.

de closure { } geeft simpelweg het eerste argument van de closure terug, d.w.z. de individuele geneste arrays. Er vindt geen transformatie of operatie plaats. Wanneer u flatMap(_:) aanroept op de numbers array, echter, in plaats van map(_:), eindigt u met een afgeplatte array van individuele nummers. In tegenstelling tot de input array numbers bevat de result array geen geneste arrays!

laten we een ander voorbeeld bekijken. Stel je voor dat je met 4 groepen giraffen werkt en één groep giraffen wilt maken die groter zijn dan een bepaalde hoogte. Zo doe je dat.:

laat giraffen =,,]
laat hoogste = giraffen.flatMap ({$0.filter({ $0 > 10 }) })
print(hoogste)
waarschuwingen verbergen

zie hoe giraffes een array van arrays bevat? In de bovenstaande code wordt de functie filter(_:) aangeroepen op elke geneste array binnen giraffes. We willen alleen hele getallen (giraffen!) die groter zijn dan 10. De resulterende arrays worden afgeplat tot één” platte ” array, en toegewezen aan tallest.

overweeg wat er zou gebeuren als we map(_:) hadden gebruikt in plaats van flatMap(_:). De resulterende array zou niet worden afgevlakt. In plaats daarvan zou het dit zijn:

, , ]

het is belangrijk op te merken dat de functie flatMap(_:) eerst map(_:) aanroept op de array-items en deze vervolgens plat maakt. Daarom werkt zoiets als het volgende niet.:

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

in de bovenstaande code verwijst naar de arrays inside numbers. Een array vermenigvuldigen met twee is onmogelijk, dus daarom werkt deze code niet.

het is slim om flatmapping te zien als het zien van een array in één dimensie minder. Je begint met een tweedimensionale array, en eindigt met een eendimensionale array na flatMap(_:).

hoe zit het met het gebruik van flatMap(_:) met opties? Laten we daar nu naar kijken.

de naam “compacte kaart” is gebaseerd op het idee dat het verwijderen van nil items uit een array de array compacter maakt. Ook de naam “flat map” komt van het afvlakken van de array. En “mapping” is een concept uit de wiskunde, waarbij je de waarden in een verzameling associeert met een andere verzameling.

met behulp van de CompactMap-functie

verwijdert de functie compactMap(_:) waarden uit de invoerreeks. Het is super handig bij het werken met optionals.

Vóór Swift 4.1, de functie flatMap(_:) (hierboven) kan ook worden gebruikt om nil waarden uit afgeplatte arrays te filteren. Sinds Swift 4.1+ gebruikt u nu de expliciete compactMap(_:) voor dit doel.

hier is een voorbeeld:

laat getallen =
laat resultaat = getallen.compactMap ({int ($0) })
print (resultaat)
Verberg waarschuwingen

zie wat er gebeurt? Het belangrijkste deel van de code is Int(). Dit neemt een individuele string van numbers met en probeert te converteren naar een geheel getal, met de Int() initializer.

deze Int() initializer is failable: het kan nil – een optioneel-retourneren, dus het retourtype is Int?. Als gevolg hiervan is het retourtype van de mapping transformatie – een array van optionele gehele getallen.

de functie compactMap(_:) verwijdert automatisch nil elementen uit de geretourneerde array, na het aanroepen van map(_:) erop. Als zodanig, het is return type is niet-optioneel.

in bovenstaande code is het type result . Als u map(_:) zou hebben gebruikt, zou het retourtype zijn geweest. En je zou een extra stap nodig hebben om de waarden uit de array te pakken, om ermee te werken.

waarom FlatMap en CompactMap gebruiken?

voordat we de real-world use cases van flatmap en compactmap bespreken, laten we een korte samenvatting maken van deze functies van hogere orde en hun doeleinden.

  1. de functie map(_:) past een afsluiting toe op een invoercollectie, en geeft de getransformeerde verzameling
  2. terug de functie flatMap(_:) doet hetzelfde, en het maakt ook de resulterende verzameling
  3. plat de functie compactMap(_:) doet hetzelfde als map(_:), en het verwijdert ook nil uit de resulterende verzameling

werken met map(_:), flatMap(_:) en compactMap(_:) maakt het soms moeilijk voor te stellen hun praktische use cases. Laten we bespreken waarom je ze wilt gebruiken.

het gebruik van functies zoals map (_:) om transformaties toe te passen op reeksen heeft een paar voordelen:

  • het is beknopter dan het gebruik van een lus for, omdat u geen tijdelijke variabelen en een blok met meerdere regels for in { } nodig hebt.
  • u kunt doorgaans een aanroep schrijven naar map(_:) op één regel, waardoor uw code (meestal) leesbaarder wordt.
  • functies zoals map(_:) kunnen worden geketend, zodat u meerdere transformaties één voor één op een reeks kunt toepassen.

in het algemeen zijn functies met een hogere orde nuttig omdat ze u toelaten een functie toe te passen op een reeks waarden. In plaats van de transformatie procedureel te coderen, kun je gewoon de functie toepassen en een resultaat terugkrijgen.

de meest praktische toepassing voor flatMap(_:) is het werken met invoerwaarden die gegroepeerd of genest zijn, maar de gewenste uitvoerwaarde moet eendimensionaal zijn.

u kunt bijvoorbeeld in een Muziek-app 3 arrays hebben: nummers, artiesten en afspeellijsten. Je combineert ze in één array, roept er flatMap(_:) op Aan, selecteert de nummers, artiesten en afspeellijsten waarvoor isFavorite true is, en eindigt met een platte lijst met items die zijn favorieten.

een praktijkvoorbeeld voor compactMap(_:) werkt met een transformatie die nilkan retourneren. U bespaart uzelf een paar triviale stappen door compactMap(_:) nil waarden onmiddellijk te laten filteren. Een extra voordeel is compactMap(_:) ‘ s niet-optionele return type; de filter(_:) functie, ter vergelijking, zou een optionele waarde hebben geretourneerd als u uitgefilterd nil.

u kunt flatMap(_:) en compactMap(_:) combineren, en zelfs filter(_:) of reduce(_:_:). Stel je voor dat je een social media app aan het bouwen bent. U wilt een tijdlijn van berichten voor een gebruiker te construeren. U gebruikt 3 queries om post-ID ‘ s voor de gebruiker te selecteren, bijvoorbeeld uit volgers berichten, advertenties, en trending onderwerpen.

  • u kunt map(_:) gebruiken om deze ID ‘ s uit te breiden naar werkelijke Post objecten
  • u kunt flatMap(_:) gebruiken om de 3 groepen in één verzameling te plakken
  • u kunt compactMap(_:) gebruiken om berichten die niet konden worden uitgevouwen

Neat!

word aangenomen als iOS-ontwikkelaar

leer iOS-apps bouwen met Swift 5

meld je aan voor mijn iOS-ontwikkelcursus en leer hoe je je carrière als professionele iOS-ontwikkelaar kunt beginnen.

verder lezen

het is de moeite waard om meer te leren over map(_:), flatMap(_:) en compactMap(_:), omdat ze uw code beknopter en leesbaarder maken. U kunt meer functionele programmering toevoegen aan de code van uw app. Als je er eenmaal aan gewend bent, kun je niet geloven dat je je werk zonder ze kunt doen.

vooral de verschillen tussen map(_:), flatMap(_:) en compactMap(_:) zijn het vermelden waard. De eerste past een transformatie toe op een reeks, de tweede vlakt de resulterende array af, en de derde verwijdert nil waarden alvorens het resultaat terug te geven. Geweldig!

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.