Folding e riduzione
foldLeft e reduce
Folding e riduzione è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.
Combinare gli elementi in un unico valore
A volte è necessario combinare tutti gli elementi di una collezione in un unico valore, ad esempio una somma o una concatenazione. Scala mette a disposizione fold, foldLeft, foldRight e reduce per questo scopo.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
println(nums.sum)
println(nums.product)
}
}reduce: combinare senza valore iniziale
reduce combina gli elementi a coppie usando una funzione binaria. Richiede almeno un elemento; in caso contrario genera un'eccezione.
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: combinare con un valore iniziale
foldLeft accetta un valore iniziale e una funzione. È sicuro con le collezioni vuote (restituisce il valore iniziale) e consente al tipo del risultato di essere diverso dal tipo degli elementi.
Sintassi: 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)
}
}Il modello dell'accumulatore
In un fold, il primo argomento è l'accumulatore che conserva il risultato parziale, mentre il secondo è l'elemento corrente. A ogni passaggio l'accumulatore viene aggiornato.
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)
}
}Il tipo del risultato può essere diverso
Una caratteristica potente di foldLeft è che il tipo dell'accumulatore può essere diverso da quello degli elementi. Qui trasformiamo con un fold una lista di numeri in una 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: da destra
foldRight elabora gli elementi da destra verso sinistra. L'accumulatore è il secondo argomento: (x, acc) => .... La direzione è importante per le operazioni non commutative.
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)
}
}Sinistra e destra: prestazioni
foldLeft è ricorsivo in coda e non rischia l'overflow dello stack con liste grandi. foldRight su una List può causare un overflow dello stack con input molto grandi. Preferisca foldLeft, a meno che l'ordine non imponga una scelta diversa.
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)
}
}Creare una collezione con fold
I fold sono abbastanza generali da consentire di creare collezioni. Qui invertiamo una lista anteponendo ogni elemento a una lista accumulatrice.
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 per maggiore sicurezza
Poiché reduce fallisce con le collezioni vuote, reduceOption restituisce invece un Option: Some(result) quando la collezione non è vuota, None quando è vuota.
object Main {
def main(args: Array[String]): Unit = {
println(List(3, 1, 4).reduceOption(_ + _))
println(List.empty[Int].reduceOption(_ + _))
}
}fold: una variante simmetrica
fold è simile a foldLeft, ma l'accumulatore deve avere lo stesso tipo degli elementi. Viene spesso usato con collezioni parallele.
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4)
val total = nums.fold(0)(_ + _)
println(total)
}
}Contare con foldLeft
I fold possono calcolare risultati più complessi, ad esempio contare quanti elementi soddisfano una condizione, tutto in un'unica passata.
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")
}
}Verifica rapida
Qual è la differenza fondamentale tra reduce e foldLeft?
Riepilogo
Ha appreso il folding e la riduzione:
reduce— combina a coppie, senza valore iniziale, e fallisce se la collezione è vuotareduceOption— variante sicura che restituisceOptionfoldLeft— valore iniziale e accumulatore, sicuro per lo stack, con tipo del risultato flessibilefoldRight— da destra verso sinistra; attenzione allo stack con le liste grandi- I fold possono persino creare nuove collezioni
Domande Frequenti
La lezione «Folding e riduzione» è gratuita?
Sì — il testo completo di «Folding e riduzione» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.
Cosa imparerò in «Folding e riduzione»?
foldLeft e reduce Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?
Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Folding e riduzione»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?
Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- List, Vector, Set, Map
- Trasformazioni
- Folding e riduzione
- Raggruppamento e ordinamento