Scala for backendutvikling og funksjonell programmering · leksjon

reduce og aggregate

Andre måter å kombinere elementer på.

Leksjon 4 av 413 trinn

reduce og aggregate er en gratis leksjon i Scala for backendutvikling og funksjonell programmering på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Scala for backendutvikling og funksjonell programmering, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Scala for backendutvikling og funksjonell programmering inneholder totalt 4 leksjoner.

Fra fold til reduce

Noen ganger ønsker De å kombinere elementer uten å angi en separat startverdi.

reduce bruker det første elementet som startakkumulator og kombinerer resten inn i den.

Det er en slankere slektning av fold for tilfeller der elementtypen og resultattypen er den samme.

Grunnleggende om reduce

reduce tar en binær funksjon (a, b) og folder den over samlingen uten en uttrykkelig startverdi.

For en sum legger den ganske enkelt alle elementene sammen.

val xs = List(1, 2, 3, 4)
val total = xs.reduce((a, b) => a + b)

@main def run(): Unit =
  println(total)  // 10

Fellen med tomme samlinger

Fordi reduce ikke har noen startverdi, utløser et kall på en tom samling en UnsupportedOperationException.

fold og foldLeft er trygge på tomme samlinger fordi de faller tilbake på den angitte startverdien.

Bruk reduce bare når De vet at samlingen ikke er tom.

// List.empty[Int].reduce(_ + _)
// throws UnsupportedOperationException

List.empty[Int].foldLeft(0)(_ + _)  // safe, returns 0

reduceOption for sikkerhet

reduceOption returnerer en Option og gir None for en tom samling i stedet for å kaste et unntak.

Dette er den trygge måten å bruke reduce på når samlingen kan være tom.

val xs = List(5, 9, 2)
val maybeMax = xs.reduceOption(_ max _)

@main def run(): Unit =
  println(maybeMax)  // Some(9)

reduceLeft og reduceRight

I likhet med fold har reduce retningsbestemte varianter.

reduceLeft kombinerer fra venstre mot høyre, mens reduceRight kombinerer fra høyre mot venstre. Vanlig reduce gir ingen garanti for rekkefølgen i parallelle samlinger, så bruk den eksplisitte varianten når retningen er viktig.

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)

Hvorfor aggregate finnes

fold og reduce krever at akkumulator- og elementtypene henger enkelt sammen.

aggregate er den mest generelle fold-varianten: Den lar akkumulatoren ha en annen type OG forteller Scala hvordan delakkumulatorer skal slås sammen, noe som er viktig ved parallell behandling.

Signaturen til aggregate

aggregate tar et startobjekt, en seqop som folder et element inn i akkumulatoren, og en combop som slår sammen to akkumulatorer.

I en sekvensiell samling brukes combop sjelden. I en parallell samling slår den sammen resultatene fra hver del.

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)  // 10

aggregate med en annen type

Her folder aggregate en liste med ord til en samlet lengde av typen Int.

seqop legger til lengden på hvert ord, mens combop legger sammen to delsummer.

Akkumulatortypen (Int) er forskjellig fra elementtypen (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)  // 10

Parallell aggregering

Den virkelige styrken til aggregate kommer til syne med parallelle samlinger.

Hver tråd folder sin egen del med seqop, og deretter slås delene sammen med combop. De to funksjonene lar Scala dele opp og sette sammen arbeidet på en trygg måte.

// Conceptual: par splits the work
// val n = data.par.aggregate(0)(_ + _.length, _ + _)
// seqop runs per chunk, combop merges chunk results

Velge riktig verktøy

Bruk reduce eller reduceOption når resultattypen er lik elementtypen og kombinasjonen er associativ.

Bruk foldLeft når du trenger et startobjekt eller en annen resultattype i sekvensiell behandling.

Bruk aggregate når akkumulator- og elementtypene er forskjellige, og du ønsker sammenslåing som egner seg for parallell behandling.

// reduce:    same type, non-empty, associative
// foldLeft:  seed + different type, sequential
// aggregate: different type + parallel merge

Kombinere i én gjennomgang

aggregate kan beregne flere ting samtidig ved å akkumulere i en tuppel.

Her får vi både summen og antallet i én gjennomgang, og slår sammen tupler i 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)

Kort kontroll

Avgjør hvilken operasjon som er tryggest for en liste som kan være tom.

Oppsummering

reduce kombinerer elementer uten et startobjekt og bruker det første elementet som start. Den kaster et unntak for en tom samling, mens reduceOption returnerer None.

aggregate er den mest generelle fold-varianten: et startobjekt, en seqop som folder inn elementer, og en combop som slår sammen delakkumulatorer ved parallell behandling.

Velg reduce for associativ kombinasjon av samme type, foldLeft for sekvensielle fold-operasjoner med startobjekt, og aggregate når typene er forskjellige eller behandlingen skal være parallell.

Gratis å komme i gang

Lær deg Scala med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
39
Leksjoner
143

Ofte stilte spørsmål

Er leksjonen «reduce og aggregate» gratis?

Ja – hele teksten i «reduce og aggregate» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Scala for backendutvikling og funksjonell programmering-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Scala for backendutvikling og funksjonell programmering inneholder totalt 4 leksjoner.

Hva lærer jeg i «reduce og aggregate»?

Andre måter å kombinere elementer på. Du øver på Scala for backendutvikling og funksjonell programmering med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Scala for backendutvikling og funksjonell programmering?

Ingen tidligere erfaring er nødvendig. Scala for backendutvikling og funksjonell programmering på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «reduce og aggregate»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Scala for backendutvikling og funksjonell programmering-leksjonen?

Ja. Alle Scala for backendutvikling og funksjonell programmering-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Tenk rekursivt
  2. Akkumulatormønstre
  3. foldLeft og foldRight
  4. reduce og aggregate
← Tilbake til Scala for backendutvikling og funksjonell programmering