Składanie i redukowanie
foldLeft i reduce
Składanie i redukowanie 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.
Łączenie elementów w jedną wartość
Czasami trzeba połączyć wszystkie elementy kolekcji w pojedynczą wartość, na przykład sumę lub konkatenację. Scala udostępnia do tego fold, foldLeft, foldRight i reduce.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
println(nums.sum)
println(nums.product)
}
}reduce: łączenie bez wartości początkowej
reduce łączy elementy parami za pomocą funkcji binarnej. Wymaga co najmniej jednego elementu, w przeciwnym razie zgłasza wyjątek.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val total = nums.reduce((a, b) => a + b)
println(total)
val max = nums.reduce((a, b) => if (a > b) a else b)
println(max)
}
}foldLeft: łączenie z wartością początkową
foldLeft przyjmuje początkową wartość początkową oraz funkcję. Jest bezpieczne dla pustych kolekcji (zwraca wartość początkową) i pozwala, aby typ wyniku różnił się od typu elementów.
Składnia: xs.foldLeft(seed)((acc, x) => ...).
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val sum = nums.foldLeft(0)((acc, x) => acc + x)
println(sum)
val empty = List.empty[Int].foldLeft(0)(_ + _)
println(empty)
}
}Wzorzec akumulatora
W operacji fold pierwszy argument to akumulator, który przechowuje dotychczasowy wynik, a drugi to bieżący element. W każdym kroku akumulator jest aktualizowany.
object Main {
def main(args: Array[String]): Unit = {
val words = List("Scala", "is", "great")
val sentence = words.foldLeft("")((acc, w) => acc + w + " ")
println(sentence.trim)
}
}Typ wyniku może być inny
Potężną cechą foldLeft jest to, że typ akumulatora może różnić się od typu elementów. W tym przykładzie składamy listę liczb do typu String.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3)
val joined = nums.foldLeft("nums:")((acc, n) => acc + " " + n)
println(joined)
}
}foldRight: od prawej strony
foldRight przetwarza elementy od prawej do lewej. Akumulator jest drugim argumentem: (x, acc) => .... Kierunek ma znaczenie w przypadku operacji nieprzemiennych.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val left = nums.foldLeft("")((acc, x) => acc + x)
val right = nums.foldRight("")((x, acc) => acc + x)
println("foldLeft: " + left)
println("foldRight: " + right)
}
}Lewa i prawa strona a wydajność
foldLeft jest rekurencyjne ogonowo i bezpieczne dla stosu w przypadku dużych list. foldRight na obiekcie List może przepełnić stos przy bardzo dużych danych wejściowych. Należy preferować foldLeft, chyba że kolejność wymusza inne rozwiązanie.
object Main {
def main(args: Array[String]): Unit = {
val big = (1 to 100000).toList
val total = big.foldLeft(0L)((acc, x) => acc + x)
println(total)
}
}Budowanie kolekcji za pomocą fold
Operacje fold są na tyle uniwersalne, że można za ich pomocą budować kolekcje. W tym przykładzie odwracamy listę, dodając każdy element na początku listy akumulatora.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val reversed = nums.foldLeft(List.empty[Int])((acc, x) => x :: acc)
println(reversed)
}
}reduceOption dla bezpieczeństwa
Ponieważ reduce kończy się niepowodzeniem dla pustych kolekcji, reduceOption zwraca obiekt Option: Some(result), gdy kolekcja nie jest pusta, oraz None, gdy jest pusta.
object Main {
def main(args: Array[String]): Unit = {
println(List(3, 1, 4).reduceOption(_ + _))
println(List.empty[Int].reduceOption(_ + _))
}
}fold: wariant symetryczny
fold działa podobnie jak foldLeft, ale akumulator musi mieć ten sam typ co elementy. Jest często używane z kolekcjami równoległymi.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val total = nums.fold(0)(_ + _)
println(total)
}
}Zliczanie za pomocą foldLeft
Operacje fold mogą obliczać bardziej złożone wyniki, na przykład zliczać, ile elementów spełnia warunek, wykonując wszystko w jednym przejściu.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(4, 7, 2, 9, 6, 1)
val evenCount = nums.foldLeft(0)((acc, x) => if (x % 2 == 0) acc + 1 else acc)
println(s"even numbers: $evenCount")
}
}Szybkie sprawdzenie
Jaka jest kluczowa różnica między reduce a foldLeft?
Podsumowanie
Opanował(a) Pan/Pani składanie i redukcję:
reduce— łączy elementy parami, bez wartości początkowej, kończy się niepowodzeniem dla pustej kolekcjireduceOption— bezpieczny wariant zwracającyOptionfoldLeft— wartość początkowa i akumulator, bezpieczeństwo stosu, elastyczny typ wynikufoldRight— od prawej do lewej, przy dużych listach należy uważać na stos- Operacje fold mogą nawet budować nowe kolekcje
Często zadawane pytania
Czy lekcja „Składanie i redukowanie” jest bezpłatna?
Tak — pełny tekst „Składanie i redukowanie” 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 „Składanie i redukowanie”?
foldLeft i reduce Ć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 „Składanie i redukowanie”?
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
- List, Vector, Set, Map
- Przekształcenia
- Składanie i redukowanie
- Grupowanie i sortowanie