Retour au cours

le module enumerable : la puissance des itérateurs

Objectifs

  • Comprendre le rôle central du module Enumerable dans l’écosystème Ruby.
  • Utiliser les itérateurs les plus puissants : map, select, et reduce.
  • Enchaîner ces méthodes pour écrire du code de transformation de données concis et expressif.

Si vous avez compris les blocs et l’itérateur .each, vous êtes prêt pour découvrir la vraie “magie” de Ruby.

Qu’est-ce que le module Enumerable ?

Enumerable est un module qui est “mixé” (inclus) dans la plupart des classes de collection de Ruby, comme Array, Hash, et Range. Il leur fournit gratuitement des dizaines de méthodes d’itération, de recherche et de tri incroyablement puissantes.

La seule chose qu’une classe doit faire pour bénéficier de Enumerable est de définir sa propre méthode .each.

Les itérateurs essentiels

.map (ou .collect) : Transformer chaque élément

.map parcourt une collection, applique le bloc à chaque élément, et retourne un nouveau tableau contenant les résultats.

nombres = [1, 2, 3, 4]

# Créer un nouveau tableau avec le carré de chaque nombre
carres = nombres.map do |n|
  n * n
end

puts carres.inspect # => [1, 4, 9, 16]
puts nombres.inspect # => [1, 2, 3, 4] (l'original n'a pas changé)

.select (ou .find_all) : Filtrer une collection

.select parcourt une collection, applique le bloc à chaque élément, et retourne un nouveau tableau contenant uniquement les éléments pour lesquels le bloc a renvoyé une valeur “truthy” (true, mais pas false ou nil).

nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Garder uniquement les nombres pairs
nombres_pairs = nombres.select do |n|
  n.even? # La méthode .even? renvoie true si le nombre est pair
end

puts nombres_pairs.inspect # => [2, 4, 6, 8, 10]

La méthode .reject fait l’exact contraire : elle garde les éléments pour lesquels le bloc est “falsy”.

.reduce (ou .inject) : Réduire une collection à une seule valeur

.reduce est l’itérateur le plus puissant. Il permet de “réduire” une collection entière à un seul résultat en appliquant une opération de manière cumulative.

Il prend un argument initial (l’accumulateur) et un bloc. Le bloc reçoit l’accumulateur et l’élément courant, et doit retourner la nouvelle valeur de l’accumulateur.

nombres = [1, 2, 3, 4, 5]

# Calcule la somme de tous les nombres.
# L'accumulateur 'somme' commence à 0.
somme_totale = nombres.reduce(0) do |somme, n|
  somme + n
end

puts somme_totale # => 15

Le chaînage : La beauté de Ruby

La vraie puissance de ces méthodes est qu’elles peuvent être enchaînées les unes à la suite des autres pour créer des pipelines de transformation de données très lisibles.

# Prenons les nombres de 1 à 10...
resultat = (1..10)
  .select { |n| n.odd? }  # ... gardons les impairs : [1, 3, 5, 7, 9]
  .map { |n| n * n }      # ... mettons-les au carré : [1, 9, 25, 49, 81]
  .reduce(0) { |sum, n| sum + n } # ... et additionnons-les

puts resultat # => 165

Bonnes pratiques

  • Privilégiez les itérateurs fonctionnels (map, select…) plutôt que de construire manuellement des tableaux avec .each et des if. Le code est plus déclaratif (“ce que je veux”) et moins impératif (“comment le faire”).
  • Utilisez la syntaxe courte {...} pour les blocs sur une seule ligne.
  • Découvrez les autres méthodes d’Enumerable ! Il y en a des dizaines de très utiles comme .any?, .all?, .find, .count, etc.

Exercices

  1. Transformation de chaînes :

    • Vous avez un tableau ["bonjour", "monde"].
    • Utilisez .map pour créer un nouveau tableau ["BONJOUR", "MONDE"].
  2. Filtrage de mots :

    • Vous avez un tableau de mots : %w[ruby est un langage formidable].
    • Utilisez .select pour ne garder que les mots qui ont plus de 4 lettres.
  3. Calcul de produit :

    • Vous avez un tableau [2, 3, 4].
    • Utilisez .reduce pour calculer le produit de tous ces nombres (2 * 3 * 4). Quel doit être l’accumulateur initial ? (Indice : l’élément neutre de la multiplication n’est pas 0).
  4. Chaînage :

    • En une seule ligne, prenez un tableau de noms ["alice", "bob", "charlie"], ne gardez que ceux qui commencent par la lettre “a”, et mettez-les en majuscules. Le résultat attendu est ["ALICE"].