reduce i agregowanie
Pozna Pan/Pani inne sposoby łączenia elementów.
reduce i agregowanie to bezpłatna lekcja Scala for Backend Engineering & Functional Programming na CoddyKit. To lekcja 4 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.
Od fold do reduce
Czasami trzeba połączyć elementy bez podawania osobnej wartości początkowej.
reduce wykorzystuje pierwszy element jako początkowy akumulator i łączy z nim pozostałe elementy.
To uproszczony odpowiednik fold, przeznaczony do przypadków, w których typ elementów i typ wyniku są takie same.
Podstawy reduce
reduce przyjmuje funkcję binarną (a, b) i stosuje ją do całej kolekcji bez jawnej wartości początkowej.
W przypadku sumy po prostu dodaje do siebie wszystkie elementy.
val xs = List(1, 2, 3, 4)
val total = xs.reduce((a, b) => a + b)
@main def run(): Unit =
println(total) // 10Pułapka pustej kolekcji
Ponieważ reduce nie ma wartości początkowej, wywołanie go dla pustej kolekcji powoduje wyjątek UnsupportedOperationException.
fold i foldLeft są bezpieczne dla pustych kolekcji, ponieważ wykorzystują przekazaną wartość początkową.
Po reduce należy sięgać tylko wtedy, gdy wiadomo, że kolekcja nie jest pusta.
// List.empty[Int].reduce(_ + _)
// throws UnsupportedOperationException
List.empty[Int].foldLeft(0)(_ + _) // safe, returns 0reduceOption dla bezpieczeństwa
reduceOption zwraca wartość typu Option, podając None dla pustej kolekcji zamiast zgłaszać wyjątek.
To bezpieczny sposób redukcji, gdy kolekcja może być pusta.
val xs = List(5, 9, 2)
val maybeMax = xs.reduceOption(_ max _)
@main def run(): Unit =
println(maybeMax) // Some(9)reduceLeft i reduceRight
Podobnie jak fold, reduce ma warianty określające kierunek działania.
reduceLeft łączy elementy od lewej do prawej, a reduceRight — od prawej do lewej. Zwykłe reduce nie gwarantuje kolejności dla kolekcji równoległych, dlatego gdy kierunek ma znaczenie, należy użyć jawnie określonego wariantu.
val xs = List(1, 2, 3)
val l = xs.reduceLeft(_ - _) // (1-2)-3 = -4
val r = xs.reduceRight(_ - _) // 1-(2-3) = 2
@main def run(): Unit =
println((l, r)) // (-4, 2)Dlaczego istnieje aggregate
fold i reduce wymagają prostego powiązania typu akumulatora z typem elementów.
aggregate to najbardziej ogólna forma fold: pozwala użyć innego typu akumulatora ORAZ określić sposób łączenia częściowych akumulatorów przez Scalę, co ma znaczenie podczas przetwarzania równoległego.
Sygnatura aggregate
aggregate przyjmuje wartość początkową, seqop, który składa element z akumulatorem, oraz combop, który łączy dwa akumulatory.
W kolekcji sekwencyjnej combop jest rzadko używany, natomiast w równoległej łączy wyniki poszczególnych fragmentów.
val xs = List(1, 2, 3, 4)
val sum = xs.aggregate(0)(
(acc, x) => acc + x, // seqop
(a, b) => a + b // combop
)
@main def run(): Unit = println(sum) // 10aggregate z innym typem
W tym przykładzie aggregate składa listę słów w łączną długość typu Int.
seqop dodaje długość każdego słowa, a combop dodaje do siebie dwie częściowe sumy.
Typ akumulatora (Int) różni się od typu elementów (String).
val words = List("hi", "there", "you")
val chars = words.aggregate(0)(
(acc, w) => acc + w.length,
(a, b) => a + b
)
@main def run(): Unit = println(chars) // 10Agregacja równoległa
Prawdziwa siła aggregate ujawnia się w kolekcjach równoległych.
Każdy wątek składa własny fragment za pomocą seqop, a następnie fragmenty są łączone za pomocą combop. Te dwie funkcje pozwalają Scali bezpiecznie dzielić i ponownie łączyć pracę.
// Conceptual: par splits the work
// val n = data.par.aggregate(0)(_ + _.length, _ + _)
// seqop runs per chunk, combop merges chunk resultsWybór właściwego narzędzia
Proszę użyć reduce lub reduceOption, gdy typ wyniku jest taki sam jak typ elementów, a operacja łączenia jest łączna.
Proszę użyć foldLeft, gdy w przetwarzaniu sekwencyjnym potrzebują Państwo wartości początkowej lub innego typu wyniku.
Proszę użyć aggregate, gdy typy akumulatora i elementów różnią się oraz potrzebują Państwo łączenia przystosowanego do przetwarzania równoległego.
// reduce: same type, non-empty, associative
// foldLeft: seed + different type, sequential
// aggregate: different type + parallel mergeŁączenie w jednym przebiegu
aggregate może obliczać kilka wartości jednocześnie, gromadząc je w krotce.
W tym przykładzie otrzymujemy zarówno sumę, jak i liczbę elementów w jednym przebiegu, łącząc krotki w combop.
val xs = List(2, 4, 6, 8)
val (s, c) = xs.aggregate((0, 0))(
(acc, x) => (acc._1 + x, acc._2 + 1),
(a, b) => (a._1 + b._1, a._2 + b._2)
)
@main def run(): Unit = println((s, c)) // (20, 4)Szybkie sprawdzenie
Proszę zdecydować, która operacja jest najbezpieczniejsza dla listy, która może być pusta.
Podsumowanie
reduce łączy elementy bez wartości początkowej, używając pierwszego elementu jako początku; dla pustej kolekcji zgłasza wyjątek, natomiast reduceOption zwraca None.
aggregate to najbardziej ogólna forma fold: przyjmuje wartość początkową, seqop do składania elementów oraz combop do łączenia częściowych akumulatorów podczas pracy równoległej.
Proszę wybrać reduce do łączenia elementów tego samego typu za pomocą operacji łącznej, foldLeft do sekwencyjnego składania z wartością początkową, a aggregate, gdy typy się różnią lub przetwarzanie odbywa się równolegle.
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 „reduce i agregowanie” jest bezpłatna?
Tak — pełny tekst „reduce i agregowanie” 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 „reduce i agregowanie”?
Pozna Pan/Pani inne sposoby łączenia elementów. Ć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 4 z 4.
Ile czasu zajmuje lekcja „reduce i agregowanie”?
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