foldLeft i foldRight
Zredukuje Pan/Pani kolekcje do jednej wartości.
foldLeft i foldRight to bezpłatna lekcja Scala for Backend Engineering & Functional Programming na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Scala for Backend Engineering & Functional Programming, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.
Redukowanie kolekcji za pomocą fold
Operacja fold sprowadza kolekcję do jednej wartości, wielokrotnie łącząc elementy za pomocą akumulatora.
Poznany wzorzec akumulatora jest dokładnie tym, co abstrahuje fold. Zamiast samodzielnie pisać funkcję pomocniczą, przekazuje się wartość początkową i funkcję łączącą.
Podstawy foldLeft
foldLeft przyjmuje początkowy akumulator oraz funkcję (acc, element) i przechodzi po kolekcji od lewej do prawej.
Na każdym kroku zastępuje akumulator wynikiem funkcji.
val xs = List(1, 2, 3, 4)
val total = xs.foldLeft(0)((acc, x) => acc + x)
@main def run(): Unit =
println(total) // 10Sposób grupowania w foldLeft
foldLeft grupuje działania od lewej. Dla List(1, 2, 3) i wartości początkowej z oblicza f(f(f(z, 1), 2), 3).
Akumulator jest lewym argumentem, więc narasta podczas przechodzenia w prawo po liście.
// List(1, 2, 3).foldLeft(0)(_ + _)
// = ((0 + 1) + 2) + 3
// = 6Podstawy foldRight
foldRight również łączy elementy, ale rozpoczyna od prawej strony.
Jego funkcja przyjmuje argumenty (element, acc), gdzie element znajduje się po lewej, a akumulator po prawej.
val xs = List(1, 2, 3, 4)
val total = xs.foldRight(0)((x, acc) => x + acc)
@main def run(): Unit =
println(total) // 10Sposób grupowania w foldRight
foldRight grupuje działania od prawej. Dla List(1, 2, 3) i wartości początkowej z oblicza f(1, f(2, f(3, z))).
Wartość początkowa znajduje się skrajnie po prawej, a elementy listy są łączone od końca do środka.
// List(1, 2, 3).foldRight(0)(_ + _)
// = 1 + (2 + (3 + 0))
// = 6Gdy kierunek ma znaczenie
Dla działań łącznych i przemiennych, takich jak suma lub iloczyn, oba sposoby zwracają ten sam wynik.
W przypadku działań nieprzemiennych, takich jak odejmowanie lub budowanie listy, kierunek zmienia wynik. Należy wybrać go świadomie.
val xs = List(1, 2, 3)
val l = xs.foldLeft(0)(_ - _) // ((0-1)-2)-3 = -6
val r = xs.foldRight(0)(_ - _) // 1-(2-(3-0)) = 2
@main def run(): Unit =
println((l, r)) // (-6, 2)Budowanie listy
foldRight jest naturalnym wyborem do odtwarzania listy w jej kolejności, ponieważ działa od ogona do początku, a dodawanie elementów na początku zachowuje ich pozycje.
W ten sposób każdy element jest przekształcany przy zachowaniu kolejności.
val xs = List(1, 2, 3)
val doubled = xs.foldRight(List.empty[Int]) { (x, acc) =>
(x * 2) :: acc
}
@main def run(): Unit =
println(doubled) // List(2, 4, 6)foldLeft odwraca kolejność
Jeśli lista jest budowana za pomocą foldLeft i dodawania elementów na początku, wynik będzie odwrócony, ponieważ elementy są dodawane od przodu podczas przechodzenia w prawo.
Czasami jest to dokładnie pożądany rezultat.
val xs = List(1, 2, 3)
val rev = xs.foldLeft(List.empty[Int]) { (acc, x) =>
x :: acc
}
@main def run(): Unit =
println(rev) // List(3, 2, 1)Bezpieczeństwo stosu
foldLeft jest rekurencyjny ogonowo i działa jak pętla, więc jest bezpieczny nawet dla ogromnych kolekcji.
foldRight dla List nie jest rekurencyjny ogonowo i przy bardzo długich listach może przepełnić stos. Gdy kolejność od prawej do lewej nie jest potrzebna, należy preferować foldLeft.
// Safe even for millions of elements:
val n = (1 to 1000000).foldLeft(0L)(_ + _)
// foldRight on a long List risks StackOverflowErrorZmiana typu wyniku
Typ akumulatora może różnić się od typu elementów.
W tym przypadku lista intów jest składana do napisu, więc wartością początkową jest pusty napis, a każdy krok coś do niego dopisuje.
Typ operacji fold wynika z wartości początkowej.
val xs = List(1, 2, 3)
val s = xs.foldLeft("")((acc, x) => acc + x.toString)
@main def run(): Unit =
println(s) // "123"Fold jako szwajcarski scyzoryk
Wiele operacji na listach to szczególne przypadki fold: suma, iloczyn, długość, maksimum, map, filter i reverse.
Rozpoznanie stojącej za nimi operacji fold pomaga pisać zwięzły, deklaratywny kod zamiast ręcznie tworzonej rekurencji.
val xs = List(4, 1, 7, 3)
val maxV = xs.foldLeft(Int.MinValue)(_ max _)
val len = xs.foldLeft(0)((acc, _) => acc + 1)
@main def run(): Unit =
println((maxV, len)) // (7, 4)Szybkie sprawdzenie
Przeanalizuj kierunek operacji fold oraz położenie wartości początkowej.
Podsumowanie
foldLeft przechodzi od lewej do prawej, z akumulatorem po lewej, i oblicza ((z op a) op b) op c. Jest rekurencyjny ogonowo i bezpieczny dla stosu.
foldRight przechodzi od prawej do lewej, z wartością początkową po prawej, i oblicza a op (b op (c op z)). Nadaje się do budowania list z zachowaniem kolejności, ale przy długich listach może przepełnić stos.
Wartość początkowa określa typ wyniku, dlatego operacje fold mogą przekształcać kolekcję w dowolną wartość.
Ucz się Scala dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 39
- Lekcje
- 143
Często zadawane pytania
Czy lekcja „foldLeft i foldRight” jest bezpłatna?
Tak — pełny tekst „foldLeft i foldRight” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Scala for Backend Engineering & Functional Programming, przejdź na CoddyKit PRO. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.
Co nauczysz się w „foldLeft i foldRight”?
Zredukuje Pan/Pani kolekcje do jednej wartości. Ćwiczysz Scala for Backend Engineering & Functional Programming z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Scala for Backend Engineering & Functional Programming?
Nie wymagamy żadnego doświadczenia. Scala for Backend Engineering & Functional Programming w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „foldLeft i foldRight”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Scala for Backend Engineering & Functional Programming?
Tak. Każda lekcja Scala for Backend Engineering & Functional Programming zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Myślenie rekurencyjne
- Wzorce akumulatora
- foldLeft i foldRight
- reduce i agregowanie