Scala for Backend Engineering & Functional Programming · Leçon

Réduction et pliage

foldLeft et reduce

Leçon 3 sur 413 étapes

Réduction et pliage est une leçon Scala for Backend Engineering & Functional Programming gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Scala for Backend Engineering & Functional Programming, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.

Combiner les éléments en une seule valeur

Il faut parfois combiner tous les éléments d'une collection en une seule valeur, par exemple une somme ou une concaténation. Scala fournit fold, foldLeft, foldRight et reduce pour cela.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    println(nums.sum)
    println(nums.product)
  }
}

reduce : combiner sans valeur initiale

reduce combine les éléments deux à deux à l'aide d'une fonction binaire. Il nécessite au moins un élément ; sinon, il lève une exception.

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 : combiner avec une valeur initiale

foldLeft prend une valeur initiale et une fonction. Il est sûr avec les collections vides (il renvoie la valeur initiale) et permet au type du résultat de différer du type des éléments.

Syntaxe : 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)
  }
}

Le schéma de l'accumulateur

Dans un fold, le premier argument est l'accumulateur qui conserve le résultat en cours, et le second est l'élément courant. Chaque étape met à jour l'accumulateur.

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)
  }
}

Le type du résultat peut différer

Une fonctionnalité puissante de foldLeft est que le type de l'accumulateur peut différer de celui des éléments. Ici, nous transformons une liste de nombres en un 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 : de droite à gauche

foldRight traite les éléments de droite à gauche. L'accumulateur est le second argument : (x, acc) => .... Le sens est important pour les opérations non commutatives.

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)
  }
}

De gauche à droite ou de droite à gauche : les performances

foldLeft est récursif terminal et ne risque pas de dépasser la pile avec les grandes listes. foldRight appliqué à une List peut provoquer un dépassement de pile avec des entrées très volumineuses. Préférez foldLeft, sauf si l'ordre impose l'inverse.

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)
  }
}

Construire une collection avec fold

Les folds sont suffisamment généraux pour construire des collections. Ici, nous inversons une liste en ajoutant chaque élément en tête d'une liste accumulateur.

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 pour plus de sûreté

Comme reduce échoue sur les collections vides, reduceOption renvoie plutôt un Option : Some(result) lorsque la collection n'est pas vide, et None lorsqu'elle l'est.

object Main {
  def main(args: Array[String]): Unit = {
    println(List(3, 1, 4).reduceOption(_ + _))
    println(List.empty[Int].reduceOption(_ + _))
  }
}

fold : une variante symétrique

fold ressemble à foldLeft, mais l'accumulateur doit avoir le même type que les éléments. Il est souvent utilisé avec des collections parallèles.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val total = nums.fold(0)(_ + _)
    println(total)
  }
}

Compter avec foldLeft

Les folds peuvent calculer des résultats plus riches, comme le nombre d'éléments qui satisfont une condition, en un seul parcours.

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")
  }
}

Vérification rapide

Quelle est la différence essentielle entre reduce et foldLeft ?

Récapitulatif

Vous avez appris à utiliser les folds et les réductions :

  • reduce — combine deux à deux, sans valeur initiale, et échoue si la collection est vide
  • reduceOption — variante sûre renvoyant un Option
  • foldLeft — valeur initiale et accumulateur, sans risque de dépassement de pile, type de résultat flexible
  • foldRight — de droite à gauche ; attention à la pile avec les grandes listes
  • Les folds peuvent même construire de nouvelles collections
Gratuit pour commencer

Apprends Scala avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
39
Leçons
143

Questions Fréquemment Posées

La leçon « Réduction et pliage » est-elle gratuite ?

Oui — le texte complet de « Réduction et pliage » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Scala for Backend Engineering & Functional Programming, passe à CoddyKit PRO. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Réduction et pliage » ?

foldLeft et reduce Tu pratiques Scala for Backend Engineering & Functional Programming avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Scala for Backend Engineering & Functional Programming ?

Aucune expérience préalable n'est requise. Scala for Backend Engineering & Functional Programming sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Réduction et pliage » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Scala for Backend Engineering & Functional Programming ?

Oui. Chaque leçon Scala for Backend Engineering & Functional Programming inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. List, Vector, Set, Map
  2. Transformations
  3. Réduction et pliage
  4. Regroupement et tri
← Retour à Scala for Backend Engineering & Functional Programming