napsal Reinder de Vries 12. července 2020 v App Development, Swift
Swift má spoustu funkcí, které jsou užitečné pro transformaci sbírek a sekvencí. V tomto tutoriálu budeme diskutovat map(_:)
, flatMap(_:)
a compactMap(_:)
.
zde je to, na co se zaměříme:
- jak
map(_:)
transformuje kolekci nebo sekvenci použitím uzávěru na ni - jak
flatMap(_:)
může vyrovnat vstupní pole, po volánímap(_:)
- jak
compactMap(_:)
odstranínil
ze vstupního pole
v předchozím tutoriálu jsme diskutovali o tom, jak můžete použít filter(_:)
a reduce(_:)
. Tyto funkce vyššího řádu jsou velmi užitečné pro transformaci sbírek stručným a bystrým způsobem.
připraven? Jdeme.
- použití funkce mapy v Swift
- použití funkce FlatMap
- použití funkce CompactMap
- Proč používat FlatMap a CompactMap?
- další čtení
ještě nejste obeznámeni s uzávěry nebo funkcemi vyššího řádu? Nezapomeňte si je nejprve přečíst:
- Ultimate Guide to Closures in Swift
- Map, Reduce and Filter in Swift
použitím funkce mapy ve službě Swift
jako rychlého obnovení funkcí vyššího řádu ve službě Swift je naším výchozím bodem funkce map(_:)
. Tato funkce aplikuje transformaci na každý z prvků v sekvenci, jako je pole nebo slovník.
zde je příklad:
nechť výsledek = čísla.mapa({ $0 * $0 })
tisk (výsledek)
pojďme to rozdělit:
nejprve vytvoříme pole numbers
s několika celočíselnými hodnotami. Poté je funkce map(_:)
volána na numbers
a její výsledek je přiřazen result
.
funkce map(_:)
má jeden parametr, uzávěr, který vrací výsledek .
odpovídá prvnímu parametru uzávěru, tj. číslu z
numbers
, které se transformuje.
počítáme čtverec každého čísla v numbers
. V podstatě je operace volána na každém čísle v
numbers
a výsledné pole je přiřazeno result
. Transformujete – nebo „mapujete“ – jedno pole do druhého.
transformace pole pomocí map(_:)
je podobná použití smyčky for, ale mnohem stručnější. Takhle:
let numbers = var result = ()for number in numbers { result += }print(result)
tady je další způsob, jak se na to podívat. S map(_:)
se vstupní pole čísel transformuje na jiné pole čísel. Takhle:
2 => 2 * 2 => 43 => 3 * 3 => 94 => 4 * 4 => 165 => 5 * 5 => 25
funkce jako map(_:)
se nazývají funkce vyššího řádu, protože berou funkci jako vstup na rozdíl od běžných hodnot. Funkce vyššího řádu mohou také výstupovat funkce, což je užitečné pro programovací paradigma zvané funkční programování.
technicky můžete volat funkce vyššího řádu jako map(_:)
na libovolné sekvenci. To zahrnuje sbírky jako pole, slovníky a sady, rozsahy jako 1...100
a tzv. Cokoli, co vypadá jako“ seznam “ hodnot, v podstatě.
probereme, proč jsou funkce vyššího řádu užitečné na konci tohoto tutoriálu. Pojďme se nejprve dozvědět o flatMap(_:)
a compactMap(_:)
.

získejte najat jako vývojář iOS
Naučte se vytvářet aplikace pro iOS 14 pomocí Swift 5
přihlaste se do mého kurzu vývoje iOS a naučte se, jak začít svou kariéru jako profesionální vývojář iOS.
pomocí funkce FlatMap
je funkce flatMap(_:)
podobná map(_:)
kromě toho, že“ zplošťuje “ výsledné pole. Zde je příklad:
nechť výsledek = čísla.flatMap ({$0 })
tisk (výsledek)
výše uvedený kód začíná vnořeným polem celých čísel. Pole numbers
se skládá z pole 3 polí, z nichž každé obsahuje 3 čísla.
uzávěr { }
jednoduše vrátí první argument uzávěru, tj. jednotlivá vnořená pole. Žádná transformace nebo operace se neděje. Když zavoláte flatMap(_:)
na pole numbers
, místo map(_:)
skončíte se zploštělým polem jednotlivých čísel. Na rozdíl od vstupního pole numbers
pole výsledků neobsahuje vnořená pole!
podívejme se na další příklad. Představte si, že pracujete se 4 skupinami žiraf a chcete vytvořit jednu jedinou skupinu žiraf, které jsou vyšší než určitá výška. Zde je návod, jak to udělat:
nechť nejvyšší = žirafy.flatMap ({$0.filtr({ $0 > 10 }) })
tisk(nejvyšší)
podívejte se, jak giraffes
obsahuje pole polí? Ve výše uvedeném kódu je funkce filter(_:)
volána na každém vnořeném poli uvnitř giraffes
. Chceme jen celá čísla (žirafy!), které jsou větší než 10
. Výsledná pole jsou zploštěna do jednoho“ plochého “ pole a přiřazena tallest
.
zvažte, co by se stalo, kdybychom místo flatMap(_:)
použili map(_:)
. Výsledné pole by nebylo zploštělé. Místo toho by to bylo toto:
, , ]
je důležité si uvědomit, že funkce flatMap(_:)
nejprve zavolá map(_:)
na položky pole a poté ji zploští. To je důvod, proč něco jako následující nefunguje:
let numbers = , , ]let result = numbers.flatMap({ * 2 })
ve výše uvedeném kódu odkazuje na pole uvnitř čísel. Vynásobení pole dvěma je nemožné, proto tento kód nefunguje.
je chytré přemýšlet o flatmapping jako vidět pole v jedné menší dimenzi. Začnete s dvourozměrným polem a skončíte s jednorozměrným polem po flatMap(_:)
.
a co použití flatMap(_:)
s volitelnými? Podívejme se na to dále.
název „compact map“ je založen na myšlence, že odstraněním nil
položek z pole je pole kompaktnější. Podobně název „plochá mapa“ pochází ze zploštění pole. A „mapování“ je koncept z matematiky, kde spojujete hodnoty v jedné sadě s jinou sadou.
pomocí funkce CompactMap
funkce compactMap(_:)
odstraní hodnoty nil
ze vstupního pole. Je to velmi užitečné při práci s volitelnými.
Před Swift 4.1, funkce flatMap(_:)
(výše) by mohla být také použita k odfiltrování hodnot nil
ze zploštělých polí. Od Swift 4.1+ Nyní pro tento účel používáte explicitní compactMap(_:)
.
zde je příklad:
nechť výsledek = čísla.compactMap ({Int ($0) })
tisk (výsledek)
podívejte se, co se stane? Nejdůležitější částí kódu je Int()
. Toto vezme jednotlivý řetězec z numbers
s a pokusí se převést na celé číslo s inicializátorem
Int()
.
tento inicializátor Int()
je neúspěšný: může se vrátit nil
– volitelný-takže jeho typ návratu je Int?
. Výsledkem je návratový typ transformace mapování – pole volitelných celých čísel.
funkce compactMap(_:)
automaticky odstraní nil
elementy z vráceného pole po vyvolání map(_:)
. Jako takový je typ návratu nepovinný.
ve výše uvedeném kódu je typ result
. Pokud byste použili
map(_:)
, typ návratu by byl . A vy byste potřebovali další krok k rozbalení hodnot z pole, abyste s nimi mohli pracovat.
Proč používat FlatMap a CompactMap?
než budeme diskutovat o reálných případech použití flatmap a compactmap, pojďme rychle shrnout tyto funkce vyššího řádu a jejich účely.
- funkce
map(_:)
aplikuje Uzávěr na vstupní kolekci a vrací transformovanou kolekci - funkce
flatMap(_:)
dělá totéž a také zplošťuje výslednou sbírku - funkce
compactMap(_:)
dělá totéž jakomap(_:)
a také odstraňujenil
z výsledné sbírky
práce s map(_:)
, flatMap(_:)
a compactMap(_:)
v abstraktu ztěžuje někdy představit si jejich praktické využití případy použití. Pojďme diskutovat o tom, proč byste je chtěli použít.
použití funkcí jako map (_:) pro aplikaci transformací na sekvence má několik výhod:
- je to stručnější než použití smyčky
for
, protože nepotřebujete dočasné proměnné a víceřádkový blokfor in { }
. - obvykle můžete napsat hovor na
map(_:)
na jednom řádku, což (obvykle) činí váš kód čitelnějším. - funkce jako
map(_:)
mohou být zřetězeny, takže můžete použít více transformací na sekvenci jeden po druhém.
obecně jsou funkce vyššího řádu užitečné, protože umožňují použít funkci na posloupnost hodnot. Namísto postupného kódování transformace stačí použít funkci a získat výsledek zpět.
nejpraktičtějším případem použití pro flatMap(_:)
je práce se vstupními hodnotami, které jsou seskupeny nebo vnořeny, ale požadovaná výstupní hodnota musí být jednorozměrná.
například v hudební aplikaci můžete mít 3 pole: skladby, umělce a seznamy skladeb. Zkombinujete je do jednoho pole, zavoláte na něj flatMap(_:)
, vyberete skladby, umělce a seznamy skladeb, pro které je isFavorite
true
, a skončíte s jedním plochým seznamem položek, které byly oblíbené.
praktický případ použití pro compactMap(_:)
pracuje s transformací, která může vrátit nil
. Ušetříte si několik triviálních kroků tím, že necháte compactMap(_:)
okamžitě odfiltrovat hodnoty nil
. Další výhodou je nepovinný typ návratu compactMap(_:)
; funkce filter(_:)
by ve srovnání s tím vrátila volitelnou hodnotu, pokud byste odfiltrovali nil
.
můžete kombinovat flatMap(_:)
a compactMap(_:)
a dokonce filter(_:)
nebo reduce(_:_:)
. Představte si, že budujete aplikaci pro sociální média. Chcete vytvořit časovou osu příspěvků pro uživatele. Používáte 3 dotazy k výběru ID příspěvků pro uživatele, například z příspěvků sledujících, reklam a trendových témat.
- můžete použít
map(_:)
k rozšíření těchto ID na skutečnéPost
objekty - můžete použít
flatMap(_:)
k vyrovnání 3 skupin do jedné sbírky - můžete použít
compactMap(_:)
k odstranění příspěvků, které nemohly být rozšířeny
Neat!

získejte najat jako vývojář iOS
Naučte se vytvářet aplikace pro iOS 14 pomocí Swift 5
přihlaste se do mého kurzu vývoje iOS a naučte se, jak začít svou kariéru jako profesionální vývojář iOS.
další čtení
stojí za to se dozvědět o map(_:)
, flatMap(_:)
a compactMap(_:)
, protože váš kód je stručnější a čitelnější. Do kódu aplikace můžete přidat další funkční programování. Jakmile si na ně zvyknete, nemůžete uvěřit, že byste mohli dělat svou práci bez nich.
zvláště rozdíly mezi map(_:)
, flatMap(_:)
a compactMap(_:)
stojí za zmínku. První aplikuje transformaci na sekvenci, druhá zplošťuje výsledné pole a třetí odstraní hodnoty nil
před vrácením výsledku. Úžasné!