Menu
Coddy logo textTech

group_by et partition

Fait partie de la section Logique et Flux du Journey Ruby de Coddy — leçon 25 sur 56.

Parfois, vous voulez scinder une collection plutôt que de la filtrer. Deux méthodes couvrent la plupart des cas.

group_by prend un bloc et renvoie un hash. Chaque résultat unique du bloc devient une clé, associée à un tableau des éléments qui l'ont produit :

words = ["hi", "hello", "yo", "hey", "bonjour"]
by_length = words.group_by { |w| w.length }
puts by_length.inspect
# {2=>["hi", "yo"], 5=>["hello"], 3=>["hey"], 7=>["bonjour"]}

C'est la manière la plus propre de regrouper des éléments en un seul passage.

partition est la version binaire : elle retourne une paire de tableaux, les éléments pour lesquels le bloc était vrai, et le reste :

evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
puts evens.inspect   # [2, 4]
puts odds.inspect    # [1, 3, 5]

Utilisez partition lorsqu'il y a exactement deux compartiments, group_by lorsqu'il peut y en avoir plusieurs.

challenge icon

Défi

Moyen

Lisez une liste d'entrées name:score séparées par des virgules (par exemple Alice:88,Bob:42,Charlie:75). Utilisez group_by suivi de partition pour produire un petit rapport.

Étapes :

  1. Analysez chaque entrée en une paire [name, score] (le score est un entier)
  2. Utilisez group_by sur la première lettre du name de la paire (en majuscule)
  3. Pour chaque groupe de lettres, par ordre alphabétique, utilisez partition pour séparer les entrées en réussites (score >= 60) et échecs, puis affichez une ligne par groupe :
<LETTER>: pass=<names_passing_joined_by_comma> fail=<names_failing_joined_by_comma>

Au sein de chaque groupe, les noms apparaissent dans leur ordre d'origine. Si un côté n'a pas de noms, laissez-le vide (par exemple fail=).

Pour l'entrée Alice:88,Adam:42,Bob:75,Beth:55,Cara:90, la sortie est :

A: pass=Alice fail=Adam
B: pass=Bob fail=Beth
C: pass=Cara fail=

Aide-mémoire

group_by divise une collection en un hash dont les clés sont les résultats du bloc :

words = ["hi", "hello", "yo"]
by_length = words.group_by { |w| w.length }
# {2=>["hi", "yo"], 5=>["hello"]}

partition divise en exactement deux tableaux (ceux qui correspondent et ceux qui ne correspondent pas) :

evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
# evens => [2, 4], odds => [1, 3, 5]

Utilisez partition pour deux groupes, group_by pour plusieurs.

Essayez vous-même

entries = gets.chomp.split(",").map do |s|
  name, score = s.split(":")
  [name, score.to_i]
end

# TODO: grouper par première lettre (majuscule), diviser chaque groupe par score >= 60,
#       afficher 'X: pass=... fail=...' par ordre alphabétique des lettres
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Logique et Flux