0Pricing
Scala for Backend Engineering & Functional Programming · Lezione

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 è vuota
  • reduceOption — variante sicura che restituisce Option
  • foldLeft — valore iniziale e accumulatore, sicuro per lo stack, con tipo del risultato flessibile
  • foldRight — 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

  1. List, Vector, Set, Map
  2. Trasformazioni
  3. Folding e riduzione
  4. Raggruppamento e ordinamento
← Torna a Scala for Backend Engineering & Functional Programming