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.
Défi
MoyenLisez 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 :
- Analysez chaque entrée en une paire
[name, score](le score est un entier) - Utilisez
group_bysur la première lettre dunamede la paire (en majuscule) - Pour chaque groupe de lettres, par ordre alphabétique, utilisez
partitionpour 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
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
1Les chaînes de caractères en profondeur
Aperçu des méthodes de chaînesInterpolation de chaînesParcourir les chaînesSplit et JoinRécapitulatif - String Weaver4Blocs, Procs & Lambdas
Qu'est-ce qu'un bloc ?do..end vs AccoladesLe mot-clé yieldParamètres de blocProcs et LambdasRécapitulatif - Itérateur personnalisé7Hashes - Partie 2
Hash.new avec des valeurs par défautItérer sur les HashesHashes imbriquésFusion et transformationRécapitulatif - Compteur de fréquence10Projet - Dossiers étudiants
Présentation du projetAjouter un étudiant2Intervalles
Qu'est-ce qu'un intervalle ?Méthodes d'intervalleLes intervalles dans Case / WhenRécapitulatif - Pratique des intervalles5La puissance d'Enumerable
Select et RejectChaîner MapReduce / Injectcount, all?, any?, none?group_by et partitionsort_by, min_by, max_byRécapitulatif - Data Pipeline