napsal Reinder de Vries 12. července 2020 v App Development, Swift

FlatMap a CompactMap vysvětleno v 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:

  1. jak map(_:) transformuje kolekci nebo sekvenci použitím uzávěru na ni
  2. jak flatMap(_:) může vyrovnat vstupní pole, po volání map(_:)
  3. 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.

  1. použití funkce mapy v Swift
  2. použití funkce FlatMap
  3. použití funkce CompactMap
  4. Proč používat FlatMap a CompactMap?
  5. 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ť čísla =
nechť výsledek = čísla.mapa({ $0 * $0 })
tisk (výsledek)
skrýt varování

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ť čísla =,,]
nechť výsledek = čísla.flatMap ({$0 })
tisk (výsledek)
skrýt varování

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ť žirafy =,,]
nechť nejvyšší = žirafy.flatMap ({$0.filtr({ $0 > 10 }) })
tisk(nejvyšší)
skrýt varování

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ť čísla =
nechť výsledek = čísla.compactMap ({Int ($0) })
tisk (výsledek)
skrýt varování

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.

  1. funkce map(_:) aplikuje Uzávěr na vstupní kolekci a vrací transformovanou kolekci
  2. funkce flatMap(_:) dělá totéž a také zplošťuje výslednou sbírku
  3. funkce compactMap(_:) dělá totéž jako map(_:) a také odstraňuje nil 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ý blok for 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é!

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.