napisane przez Reinder de Vries dnia 12 lipca 2020 w tworzenie aplikacji, Swift

FlatMap i CompactMap wyjaśnione w języku Swift

Swift ma kilka funkcji, które są przydatne do przekształcania kolekcji i sekwencji. W tym samouczku omówimy map(_:), flatMap(_:)i compactMap(_:).

oto na czym się skupimy:

  1. jak map(_:) przekształca kolekcję lub sekwencję, stosując do niej zamknięcie
  2. jak flatMap(_:) może spłaszczyć tablicę wejściową, po wywołaniu map(_:)
  3. jak compactMap(_:) usuwa nil z tablicy wejściowej

w poprzednim samouczku omówiliśmy, w jaki sposób można używać filter(_:)i reduce(_:). Te funkcje wyższego rzędu są bardzo pomocne w przekształcaniu kolekcji w zwięzły i wnikliwy sposób.

gotowy? Chodźmy.

  1. Korzystanie z funkcji Map w języku Swift
  2. Korzystanie z funkcji FlatMap
  3. Korzystanie z funkcji CompactMap
  4. Dlaczego Warto korzystać z FlatMap i CompactMap?
  5. Czytaj dalej

nie jesteś jeszcze zaznajomiony z zamknięciami lub funkcjami wyższego rzędu? Pamiętaj, aby najpierw przeczytać te:

  • najlepszy przewodnik po zamknięciach w języku Swift
  • Mapuj, zmniejszaj i filtruj w języku Swift

Korzystanie z funkcji Map w języku Swift

jako szybkiego odświeżania funkcji wyższego rzędu w języku Swift, naszym punktem wyjścia jest funkcja map(_:). Funkcja ta stosuje transformację do każdego z elementów w sekwencji, jak tablica lub słownik.

oto przykład:

let numbers =
let result = numbers.mapka({ $0 * $0 })
print (wynik)
Ukryj Ostrzeżenia

Podzielmy to:

najpierw tworzymy tablicę numbers z kilkoma wartościami całkowitymi. Następnie funkcja map(_:) jest wywoływana na numbers, a jej wynik jest przypisywany do result.

funkcja map(_:) ma jeden parametr, zamknięcie, które zwraca wynik . odpowiada pierwszemu parametrowi zamknięcia, czyli liczbie z numbers, która jest przekształcana.

obliczamy kwadrat każdej liczby w numbers. Zasadniczo operacja jest wywoływana na każdej liczbie w numbers, a wynikowa tablica jest przypisana do result. Przekształcasz – lub „mapujesz” – jedną tablicę w drugą.

przekształcenie tablicy za pomocą map(_:) jest podobne do użycia pętli for, ale znacznie bardziej zwięzłe. O tak.:

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

oto inny sposób, aby na to spojrzeć. Z map(_:) wejściowa tablica liczb jest przekształcana w inną tablicę liczb. O tak.:

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

funkcje takie jak map(_:) nazywane są funkcjami wyższego rzędu, ponieważ przyjmują funkcję jako dane wejściowe w przeciwieństwie do zwykłych wartości. Funkcje wyższego rzędu mogą również generować funkcje, co jest przydatne w paradygmacie programowania zwanym programowaniem funkcyjnym.

technicznie można wywoływać funkcje wyższego rzędu, takie jak map(_:)W dowolnej sekwencji. Obejmuje to kolekcje, takie jak tablice, słowniki i zestawy, zakresy, takie jak 1...100 i tak zwane Iteratory. Wszystko, co wygląda jak” lista ” wartości, w zasadzie.

omówimy, dlaczego funkcje wyższego rzędu są przydatne na końcu tego samouczka. Przejdźmy najpierw do poznania flatMap(_:)i compactMap(_:).

Zostań programistą iOS

Naucz się tworzyć aplikacje na iOS 14 za pomocą Swift 5

Zapisz się na mój kurs rozwoju iOS i dowiedz się, jak rozpocząć karierę jako profesjonalny programista iOS.

używając funkcji FlatMap

funkcja flatMap(_:) jest podobna do map(_:) z tym wyjątkiem, że „spłaszcza” wynikową tablicę. Oto przykład:

let numbers =,,]
let result = numbers.flatMap ({$0 })
print (result)
Ukryj Ostrzeżenia

powyższy kod zaczyna się od zagnieżdżonej tablicy liczb całkowitych. Tablica numbers składa się z tablicy 3 tablic, z których każda zawiera 3 liczby.

zamknięcie { } po prostu zwraca pierwszy argument zamknięcia, tzn. poszczególne zagnieżdżone tablice. Nie dokonuje się żadna transformacja ani operacja. Gdy jednak wywołujesz flatMap(_:) na tablicy numbers, zamiast map(_:), otrzymasz spłaszczoną tablicę pojedynczych numerów. W przeciwieństwie do tablicy wejściowej numbers, tablica wynikowa nie zawiera zagnieżdżonych tablic!

spójrzmy na inny przykład. Wyobraź sobie, że pracujesz z 4 grupami żyraf i chcesz stworzyć jedną grupę żyraf, które są wyższe niż określony wzrost. Oto jak to zrobić:

let giraffes =,,]
let giraffes = żyrafy.flatMap ({ $0.filtr({ $0 > 10 }) })
druk (najwyższy)
Ukryj Ostrzeżenia

zobacz, jak giraffes zawiera tablicę tablic? W powyższym kodzie funkcja filter(_:)jest wywoływana na każdej zagnieżdżonej tablicy wewnątrz giraffes. Chcemy tylko liczby całkowite (żyrafy!), które są większe niż 10. Powstałe tablice są spłaszczone do jednej” płaskiej ” tablicy i przypisane do tallest.

zastanów się, co by się stało, gdybyśmy użyli map(_:) zamiast flatMap(_:). Wynikowa tablica nie zostałaby spłaszczona. Zamiast tego byłoby to:

, , ]

należy pamiętać, że funkcja flatMap(_:) najpierw wywołuje map(_:) na elementach tablicy, a następnie ją spłaszcza. Dlatego coś takiego nie działa:

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

w powyższym kodzie odnosi się do tablic wewnątrz liczb. Mnożenie tablicy przez dwa jest niemożliwe, dlatego ten kod nie działa.

mądrze jest myśleć o flatmapingu jako o widzeniu tablicy w jednym wymiarze mniej. Zaczynasz z dwuwymiarową tablicą, a kończysz z jednowymiarową tablicą po flatMap(_:).

a co z używaniem flatMap(_:) z opcjami? Spójrzmy na to dalej.

nazwa „compact map” opiera się na idei, że usunięcie elementów nil z tablicy sprawia, że tablica jest bardziej zwarta. Podobnie nazwa „płaska Mapa” pochodzi od spłaszczenia tablicy. A „mapowanie” to pojęcie z matematyki, gdzie można skojarzyć wartości w jednym zbiorze z innym zbiorem.

Korzystanie z funkcji CompactMap

funkcja compactMap(_:) usuwa nil wartości z tablicy wejściowej. Jest bardzo przydatny podczas pracy z opcjami.

Przed Swift 4.1, funkcja flatMap(_:) (powyżej) może być również używana do filtrowania wartości nil ze spłaszczonych tablic. Od Swift 4.1+ używasz teraz jawnego compactMap(_:) do tego celu.

oto przykład:

let numbers =
let result = numbers.compactMap ({Int ($0) })
print (result)
Ukryj Ostrzeżenia

Zobacz co się dzieje? Najważniejszą częścią kodu jest Int(). Pobiera pojedynczy ciąg znaków z numbers z i próbuje przekształcić go w liczbę całkowitą za pomocą inicjalizatora Int().

ten Int() inicjalizator jest nieudany: może zwrócić nil – opcjonalnie – więc jego typ powrotu to Int?. W rezultacie zwracanym typem transformacji mapowania jest – tablica opcjonalnych liczb całkowitych.

funkcja compactMap(_:) automatycznie usuwa elementy nil ze zwracanej tablicy, po wywołaniu na niej map(_:). Jako taki, jego typ powrotu nie jest opcjonalny.

w powyższym kodzie Typ result to . Jeśli użyłbyś map(_:), zwracany typ byłby . I potrzebowałbyś dodatkowego kroku, aby rozpakować wartości z tablicy, aby z nimi pracować.

dlaczego warto używać FlatMap i CompactMap?

zanim omówimy rzeczywiste przypadki użycia flatmap i compactmap, zróbmy szybkie podsumowanie tych funkcji wyższego rzędu i ich celów.

  1. funkcja map(_:) stosuje zamknięcie do wejściowej kolekcji i zwraca przekształconą kolekcję
  2. funkcja flatMap(_:) robi to samo, a także spłaszcza wynikową kolekcję
  3. funkcja compactMap(_:) robi to samo co map(_:), a także usuwa nil z wynikowej kolekcji

praca z map(_:), flatMap(_:) i compactMap(_:) w streszczeniu sprawia, że czasami trudno sobie wyobrazić ich praktyczne zastosowania. Porozmawiajmy, dlaczego chcesz ich użyć.

Używanie funkcji takich jak map ( _ 🙂 do stosowania transformacji do sekwencji ma kilka zalet:

  • jest to bardziej zwięzłe niż użycie pętli for, ponieważ nie potrzebujesz zmiennych tymczasowych i wieloliniowego bloku for in { }.
  • zazwyczaj możesz napisać połączenie do map(_:) w jednej linii, co (zwykle) sprawia, że Twój kod jest bardziej czytelny.
  • funkcje takie jak map(_:) mogą być połączone łańcuchowo, dzięki czemu można zastosować wiele przekształceń do sekwencji jeden po drugim.

ogólnie rzecz biorąc, funkcje wyższego rzędu są użyteczne, ponieważ pozwalają zastosować funkcję do sekwencji wartości. Zamiast kodować transformację proceduralnie, można po prostu zastosować funkcję i uzyskać wynik z powrotem.

najbardziej praktycznym przypadkiem użycia dla flatMap(_:) jest praca z wartościami wejściowymi, które są pogrupowane lub zagnieżdżone, ale żądana wartość wyjściowa musi być jednowymiarowa.

możesz, na przykład w aplikacji muzycznej, mieć 3 tablice: utwory, wykonawcy i listy odtwarzania. Łączysz je w jedną tablicę, wywołujesz na niej flatMap(_:), wybierasz utwory, wykonawców i playlisty, dla których isFavorite jest true i kończysz z jedną płaską listą ulubionych elementów.

praktycznym przypadkiem użycia dla compactMap(_:) jest praca z transformacją, która może zwrócić nil. Oszczędzasz sobie kilka banalnych kroków, pozwalając compactMap(_:) odfiltrować wartości nil natychmiast. Dodatkową korzyścią jest nieobowiązkowy Typ powrotu compactMap(_:); dla porównania funkcja filter(_:)zwracałaby wartość opcjonalną, jeśli odfiltrowałbyś nil.

możesz połączyć flatMap(_:) i compactMap(_:), a nawet filter(_:) lub reduce(_:_:). Wyobraź sobie, że budujesz aplikację społecznościową. Chcesz skonstruować oś czasu postów dla użytkownika. Używasz zapytań 3, aby wybrać identyfikatory postów dla użytkownika, na przykład z postów obserwujących, reklam i trendów.

  • możesz użyć map(_:), aby rozwinąć te identyfikatory do rzeczywistych Post obiektów
  • możesz użyć flatMap(_:), aby spłaszczyć 3 grupy w jedną kolekcję
  • możesz użyć compactMap(_:), aby odrzucić posty, których nie można rozwinąć

schludnie!

Zostań programistą iOS

Naucz się tworzyć aplikacje na iOS 14 za pomocą Swift 5

Zapisz się na mój kurs rozwoju iOS i dowiedz się, jak rozpocząć karierę jako profesjonalny programista iOS.

Czytaj dalej

warto dowiedzieć się więcej o map(_:), flatMap(_:) i compactMap(_:), ponieważ dzięki nim Twój kod jest bardziej zwięzły i czytelny. Możesz dodać więcej programowania funkcyjnego do kodu aplikacji. Kiedy się do nich przyzwyczaisz, nie możesz uwierzyć, że mógłbyś wykonywać swoją pracę bez nich.

szczególnie warto zwrócić uwagę na różnice między map(_:), flatMap(_:) i compactMap(_:). Pierwszy stosuje transformację do sekwencji, drugi spłaszcza wynikową tablicę, a trzeci usuwa wartości nil przed zwróceniem wyniku. Super!

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.