0Pricing
Scala for Backend Engineering & Functional Programming · Lekcja

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 kolekcji
  • reduceOption — bezpieczny wariant zwracający Option
  • foldLeft — wartość początkowa i akumulator, bezpieczeństwo stosu, elastyczny typ wyniku
  • foldRight — 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

  1. List, Vector, Set, Map
  2. Przekształcenia
  3. Składanie i redukowanie
  4. Grupowanie i sortowanie
← Powrót do Scala for Backend Engineering & Functional Programming