kirjoittanut Reinder de Vries on July 9 2020 In App Development, Swift
Swiftissä käytät map()
, reduce()
ja filter()
kokoelmien, kuten taulukoiden ja sanakirjojen, silmukoimiseen ilman for-Loopia.
kartta -, pelkistys-ja suodatusfunktiot tulevat funktionaalisen ohjelmoinnin (FP) valtakunnasta. Niitä kutsutaan korkeamman kertaluvun funktioiksi, koska ne ottavat funktioita syötteenä. Sovellat funktiota matriisiin, esimerkiksi, muuttaaksesi sen dataa.
Swiftin kartta -, vähennä-ja suodatustoiminnot voivat olla haastavia kääriä pään ympärille. Varsinkin, jos on aina koodannut for in
silmukoita iterointiongelmien ratkaisemiseksi. Tässä oppaassa opit käyttämään map(_:)
, reduce(_:_:)
ja filter(_:)
funktioita Swiftissä.
Let ’ s get started!
- Johdatus karttaan, vähennä ja suodata
- Pikakäynnistys: Higher-Order Functions in Swift
- Using the Map Function
- Using the Reduce Function
- Using the Filter Function
- Combining Map, Reduce and Filter
- Further Reading
Introduction to Map, Reduce and Filter
When you ’ re building iOS Sovellukset, käytät tyypillisesti prosessuaalista tai olio-ohjelmointia. Funktionaalinen ohjelmointi on erilaista: se käsittelee vain funktioita. Ei muuttujia, ei tilaa, ei for-silmukoita-vain toimintoja.
Swift-ohjelmointikieli soveltuu erinomaisesti funktionaalisen ohjelmoinnin sekoittamiseen ei-funktionaalisiin lähestymistapoihin, kuten OOP. Sinun ei tarvitse tiukasti kirjoittaa funktionaalista koodia, ja konseptien omaksuminen funktionaalisesta ohjelmoinnista voi auttaa sinua oppimaan koodaamaan paremmin.
map(_:)
, reduce(_:_:)
ja filter(_:)
funktioita kutsutaan korkeamman kertaluvun funktioiksi, koska ne ottavat funktion Tulo-ja paluufunktioina ulostulona. Teknisesti Swift palauttaa operaation tulokset (ts. transformed array) käytettäessä korkeamman kertaluvun funktioita, kun taas puhdas funktionaalinen kieli palauttaa joukon funktioita. Swiftissä näiden toimintojen syötteet ovat sulkemisia.
näin ne toimivat:
-
map()
funktio soveltaa funktiota jokaiseen kokoelman esineeseen. Ajatelkaa ”kartoittamista” tai yhden arvojoukon muuttamista toiseksi arvojoukoksi. -
reduce()
funktio muuttaa kokoelman yhdeksi arvoksi. Ajattele, että se yhdistää monia arvoja yhdeksi, kuin keskiarvona joukko lukuja. -
filter()
funktio yksinkertaisesti palauttaa arvot, jotka läpäisivätif
-lausekkeen, ja vain jos tämä ehto johtitrue
.
jos ajattelet: ”katso, en tarvitse funktionaalista ohjelmointia tai tietojenkäsittelyä, koska sovellukseni eivät sitä tee!”älä sitten pysähdy tähän. Viimeaikaisissa sovellusprojekteissa olen käyttänyt karttaa, vähennä ja suodata useaan otteeseen:
- Filtering cost / revenue values with
filter(_:)
, to meet a border, before showing the values in a line graph - Average thousands of movie ratings into one value with
reduce(_:_:)
- Mapping a few operations on a string with hashtags, transforming it into a normal collection, with
map(_:)
voit ratkaista kaikki nämä ongelmat for-loop, mutta huomaat, että käyttämällä map()
, reduce()
ja filter()
johtaa suppeampi, luettava ja toimiva koodi.
Pikakäynnistys: Korkeamman kertaluvun funktiot Swiftissä
keskitymme tässä opetusohjelmassa map()
, reduce()
ja filter()
. Ennen kuin siirrymme eteenpäin, tässä on nopea katsaus Swiftin yleisimpiin korkeamman kertaluvun toimintoihin:
-
map(_:)
silmukat jokaisen kohteen päälle jonossa, soveltaa funktiota jokaiseen alkuaineeseen ja Palauttaa muunnetun tuloksen -
reduce(_:_:)
silmukat jokaisen kohteen päälle jonossa, yhdistää ne yhdeksi arvoksi ja palauttaa yhdistetyn tuloksen -
filter(_:)
silmukat jokaisen kohteen päälle jonossa ja palauttaa tuloksena olevan sekvenssin, joka sisältää vain kohteita, jotka täyttävät tietyn suodatusfunktion -
flatMap(_:)
tekee saman kuinmap(_:)
, paitsi että se litistää tuloksena sekvenssi, so. sisäkkäiset ryhmät ovat sisäkkäisiä tai ”litistettyjä”” -
compactMap(_:)
tekee saman kuinmap(_:)
, paitsi että se poistaanil
arvot syntyneestä sekvenssistä ennen sen palauttamista
voit käyttää näitä funktioita taulukoissa, sanakirjoissa, sarjoissa, vaihteluväleissä, sekvensseissä ja missä tahansa muussa Swift-tyypissä, jonka voit toistaa. Jos haluat lisätietoja compactMap(_:)
: stä ja flatMap(_:)
: stä, tutustu tähän opetusohjelmaan.
useilla Swiftin tyypeillä, kuten Array ja Dictionary, on funktiot, jotka hyväksyvät sulkeumat syötteenä. Nopea valinta:
-
contains(where:)
loops over a collection, applices a predikate (a closure) to every item, returns atrue
if a item supposes the predikate, otherwisefalse
-
first(where:)
silmukoita kokoelman päälle, soveltaa predikaatin (sulkimen) jokaiseen alkioon ja palauttaa kohteen, jos se täyttää predikaatin -
firstIndex(where:)
tekee saman kuinfirst(where:)
, paitsi että se palauttaa indeksin arvon
sijaan, voit lukea lisää näistä funktioista tässä tutoriaalissa. Se, miten where
käytetään Swiftissä, on myös mielenkiintoista, voit oppia siitä lisää tässä opetusohjelmassa.
olet nähnyt Swiftin ”map” – ja ”reduce” – funktiot kirjoitettuna map(_:)
ja reduce(_:_:)
koko tämän opetusohjelman ajan. Näiden funktioiden alaviivat ja kärjet ovat osa funktion signaalia, joka on erityinen formaatti funktioparametrien ilmaisemiseksi. Esimerkiksi map(_:)
funktiolla on yksi nimeämätön parametri, kun taas reduce(_:_:)
funktiolla on kaksi. Voit oppia lisää tästä opetusohjelma: toiminnot Swift selitti.

Hanki työpaikka iOS-kehittäjänä
Opi rakentamaan iOS 14-sovelluksia Swift 5: llä
Rekisteröidy iOS development course-kurssille ja opi aloittamaan urasi ammattimaisena iOS-kehittäjänä.
käyttämällä Karttafunktiota
map(_:)
funktio silmukoi jokaisen kokoelman kohteen ja soveltaa operaation jokaiselle kokoelman alkuaineelle. Se palauttaa kokoelman tuloksena olevia kohteita, joihin toimenpidettä sovellettiin.
katsotaanpa esimerkkiä. Meillä on joukko celsiusasteita, jotka haluat muuttaa Fahrenheitiksi.
voit käyttää for-Loopia, kuten tämä:
let celsius = var fahrenheit: = for value in celsius { fahrenheit += }print(fahrenheit)// Output:
koodi toimii hyvin, mutta se on liian monisanainen. Tarvitset muunneltavan ”auttaja” – muuttujan fahrenheit
tallentamaan lasketut muunnokset työstäessäsi niitä, ja tarvitset 3 riviä koodia itse muunnosta varten.
näin voimme tehdä saman map(_:)
funktiolla:
let fahrenheit = celsius.kartta { $0 * (9/5) + 32 }
printti(fahrenheit)
voit jopa tehdä kaiken tuon yhdellä rivillä:
.map { * (9/5) + 32 }
mitä täällä tapahtuu?
- määritellään vakio
celsius
, joukko tuplaa, ja alustetaan muutamalla satunnaisella Celsiusarvolla. - funktio
map(_:)
on nimeltääncelsius
array. Funktiolla on yksi argumentti, sulkeuma, joka muuntuu Celsiuksesta Fahrenheitiksi. - lopuksi tulostetaan tulos: muunnettu array, Celsiuksesta fahrenheitiin.
map(_:)
funktio muuttaa yhden joukon toiseksi soveltamalla funktiota jokaiseen joukon alkioon. Sulkeuma * (9/5) + 32
ottaa tuloarvon Celsius – arvona ja palauttaa arvon Fahrenheit-arvona. Saatu joukko map(_:)
rakentuu näistä muunnetuista arvoista.
katsotaan tarkemmin sulkemista. Jos olet työskennellyt sulkujen kanssa aiemmin, tunnistat lyhyen käden sulkemissyntaksin. Se on lyhyempi tapa koodata sulkeminen, jättämällä pois suuri osa sen syntaksista.
tässä suppeampi vaihtoehto:
let celsius = let fahrenheit = celsius.map({ (value: Double) -> Double in return value * (9/5) + 32})print(fahrenheit)
varsinainen map(_:)
funktiokutsu ja sen päättyminen on tämä:
··· = celsius.map({ (value: Double) -> Double in return value * (9/5) + 32})
mitä siellä tapahtuu? map(_:)
funktiota kutsutaan array celsius
. Tarvitaan yksi argumentti: tyypin (Double) -> Double
sulkeminen.
sulkemisen ensimmäinen osa, joka alkaa numerolla {
, osoittaa, että sulkemisella on yksi parametri value
tyyppiä Double
, ja sulkeminen palauttaa arvon tyyppi Double
. Sulkuelin, joka alkaa numerolla return
, yksinkertaisesti palauttaa Celsiuksen tuloksen Fahrenheit-laskelmaan.
jos vertaat lyhyen käden sulkemissyntaksia yllä olevaan laajennettuun koodiin, näet, että:
- funktiosulkeet
(
ja)
jätetään pois, koska ne voi jättää pois, kun funktiokutsun viimeinen parametri on sulkeminen. -
() -> in
– osa voidaan jättää pois, koska Swift voi päätellä, että käytät yhtäDouble
– parametria syötteenä, ja sen odotetaan palauttavanDouble
. Nyt kun olet jättänyt poisvalue
muuttujan, voit käyttää lyhyttä kättä.
-
return
lauseke voidaan jättää myös pois, koska tämän sulkemisen odotetaan palauttavan lausekkeen tuloksen joka tapauksessa.
vaikka yllä oleva koodinäyte käyttää Double
tyyppejä, ei ole rajattu näihin tyyppeihin. Syntyvällä funktion a map()
tyypillä voi olla eri tyyppi kuin mitä siihen laitetaan, ja map()
voidaan käyttää myös a Dictionary
.
siirrytään reduce(_:_:)
!
käyttäen Pelkistysfunktiota
reduce(_:_:)
funktiosilmukat jokaisen kokoelman kohteen yli ja pelkistää ne yhteen arvoon. Ajattele, että se yhdistää useita arvoja yhdeksi.
reduction-funktio on ehkä vaikeinta kartasta, reductionista, suodattimesta ymmärtää. Miten arvokokoelmasta voi siirtyä yhteen arvoon?
muutamia esimerkkejä:
- luodaan useiden arvojen summa, eli
3 + 4 + 5 = 12
- kasataan merkkijonokokoelma, eli
= "Zaphod, Trillian, Ford"
- lasketaan keskiarvoksi joukko arvoja, ts.
(7 + 3 + 10) / 3 = 7/3 + 3/3 + 10/3 = 6.667
tietojenkäsittelyssä, voit kuvitella paljon skenaarioita, kun yksinkertaisia toimintoja, kuten nämä ovat käteviä. Kuten ennenkin, voit ratkaista minkä tahansa näistä ongelmista for-Loopilla, mutta reduce(_:_:)
on yksinkertaisesti lyhyempi ja nopeampi.
näin:
let sum = arvot.vähennä (0,+)
tulosta (summa)
funktio reduce(_:_:)
vaatii kaksi parametria, alkuarvon ja sulkemisen. Yllä olevassa koodissa annetaan +
operaattori, sekin on funktio, jossa on kaksi parametria.
voit tietysti myös itse päättää:
let average = arvot.vähennä (0.0) { $0 + $1 } / kaksinkertainen (arvot.lukumäärä)
tulosta (keskiarvo)
yllä olevassa esimerkissä lasketaan kolmen luvun keskiarvo. Koodin arvojen tyypit ovat kaikki Double
. Laskemme ensin yhteen kaikki numerot ja jaamme sen sitten numeroiden määrällä.
reduce(_:_:)
funktio eroaa kahdella tavalla:
- funktiolla
reduce(_:_:)
on kaksi nimeämätöntä parametria; alkuarvolla ja sulkemisella -
reduce(_:_:)
annetulla sulkemisella on myös kaksi parametria; nykyinen vähennystulos, ja uusi arvo, joka on vähenemässä
tästä, tsekkaa tämä:
let sum = arvot.vähennä (0) {
tulosta(”\($0) + \($1) = \($0 + $1)”)
paluu $0 + $1
}
printti (summa)
yllä olevassa esimerkissä näet selvästi ja
sulkujen 2 parametria. Kun käytät koodia, tämä on lähtö saat:
0 + 7 = 77 + 3 = 1010 + 10 = 2020
Näetkö, miten aloitamme 0
: stä ja lisäämme sitten 7
? Seuraavassa vaiheessa otetaan 7
– nykyinen vähennysarvo-ja lisätään 3
, vähennyksen ”seuraava” arvo.
Tässä toinen tapa tarkastella sitä:
0 + 7(0 + 7) + 3((0 + 7) + 3) + 10
tämä tekee myös selväksi, miksi reduce(_:_:)
: lle tarvitaan alkuarvo, koska se on sulkemisen ensimmäinen ensimmäinen parametri.
pelkistystä voi olla hankala käsittää. On tärkeää ymmärtää, että operaatiota, kuten +
, sovelletaan iteratiivisesti johonkin arvojoukkoon, kunnes jäljelle jää vain yksi arvo. Sinä kirjaimellisesti vähennät arvojen määrää.
siirrytään filter(_:)
!
käyttäen Suodatusfunktiota
filter
funktio loopsahtaa jokaisen kokoelman kohteen päälle ja palauttaa kokoelman, joka sisältää vain sellaisia kohteita, jotka täyttävät include-ehdon.
se on kuin soveltaisi if
-lausetta kokoelmaan, ja pitäisi vain ne arvot, jotka läpäisevät ehdon.
tsekkaa tästä:
let even = arvot.suodatin { $0.isMultiple (of: 2) }
print (even)
yllä olevassa esimerkissä suodatat numeroita values
, jotka ovat parillisia. isMultiple(of:)
funktio palauttaa true
, kun voidaan jakaa
2
, ja false
muuten.
toisin kuin map(_:)
ja reduce(_:_:)
, sulkijan filter(_:)
on palautettava Boolen, joten joko true
tai false
. Päätteen palautuessa true
arvo pidetään, ja kun false
palautetaan, arvo jätetään pois. Näin filter(_:)
suodattaa tulorivin.
tässä hieman selkeämpi esimerkki, jossa sulkemista laajennettiin:
let values = let even = values.filter({ (value:Int) -> Bool in return value.isMultiple(of: 2)})print(even) // Output:
esimerkissä sulkeminen palauttaa Boolen arvon, joka merkitään merkinnällä -> Bool
. Se tarjoaa yhden parametrin, kokoelman kohteen, ja palauttaa tuloksen isMultiple(of:)
. Siistiä!
yhdistämällä kartta, pelkistys ja suodatus
voitko yhdistää map()
, reduce()
ja filter()
funktiot? Totta kai voit!
sanotaan, että meillä on oppilasluokka. Tiedät jokaisen oppilaan syntymävuoden. Haluat laskea kaikkien vuonna 2000 tai sen jälkeen syntyneiden opiskelijoiden yhteenlasketun iän.
Näin teet sen:
let years =
let sum = years.suodatin({ $0 >= 2000 }).kartta ({nyt – $0}).vähennä (0,+)
tulosta (summa)
yllä olevassa koodinäytteessä käytetään ketjutusta. Se käyttää yhden funktion tulosta syötteenä toiselle, yhdistämällä kartta-vähennä-suodatin. map()
funktiota kutsutaan filter()
funktion tulosjoukolle ja reduce()
funktiota kutsutaan map()
funktion tulokselle. Mahtavaa!
itse koodi on yksinkertainen:
- tehdään vakio
now
jayears
, ja annetaan sille joukko vuosia. - suodattaa pois vuoden 2000 alle jäävät vuodet, ts. pitäkää ne, joiden osalta
>= 2000
ontrue
- muunnetaan joka vuosi ikään vähentämällä vuodesta
now
- kaikki ikäluokat ylös, vähentämällä
+
otetaan mielenkiintoisempi esimerkki. Tutustu seuraava koodi, otettu opetusohjelma noin FizzBuzz:
switch (I % 3 = = 0, i % 5 == 0)
{
case (true, false):
return ”Fizz”
case (false, true):
return ”Buzz”
case (true, true):
return ”FizzBuzz”
default:
paluu ” \(i)”
}
}
olkoon tulos = Array (2…100).kartta (fizzbuzz).pienennä(”1”, { $0 + ”, ” + $1 })
printti(tulos)
Katso mitä tapahtuu? Muunnamme joukon numeroilla 2-100 joko ”Fizziksi”, ”Buzziksi” tai ”Fizzbuzziksi” map(_:)
pelin sääntöjen mukaan. Lopuksi pelkistämme tuon merkkijonojen joukon yhdeksi suureksi merkkijonoksi, jossa on reduce(_:_:)
, yhdistäen jokaisen arvon. Siistiä!
Jatkoluku
mitä jos joutuisit koodaamaan kaiken tämän for in
silmukoilla? Käyttäisit enemmän koodia. Ja se on map-reduce-Filterin teho: se on ytimekkäämpi, usein helppolukuisempi, ja — myönnä se — aika hiton siistiä!
Haluatko oppia lisää? Tutustu näihin resursseihin:
- How to Use ”where” in Swift
- FlatMap And CompactMap Explained In Swift
- the Ultimate Guide to Closures in Swift
- How To: Find an Item In An Array In Swift
- Play With Code: Binäärihaku Swiftissä
- Aloita Xcode Playgrounds

Hanki työpaikka iOS-kehittäjänä
Opi rakentamaan iOS 14-sovelluksia Swift 5: llä
Rekisteröidy iOS development course-kurssille ja opi aloittamaan urasi ammattimaisena iOS-kehittäjänä.