group_by und partition
Teil des Abschnitts Logik & Programmfluss der Ruby-Journey von Coddy — Lektion 25 von 56.
Manchmal möchten Sie eine Collection aufteilen, anstatt sie zu filtern. Zwei Methoden decken die meisten Fälle ab.
group_by nimmt einen Block entgegen und gibt einen Hash zurück. Jedes eindeutige Ergebnis des Blocks wird zu einem Schlüssel, der auf ein Array der Elemente verweist, die dieses Ergebnis erzeugt haben:
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"]}Es ist der sauberste Weg, Elemente in einem Durchgang zu gruppieren.
partition ist die binäre Version: Sie gibt ein Paar von Arrays zurück, die Elemente, für die der Block wahr war, und den Rest:
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
puts evens.inspect # [2, 4]
puts odds.inspect # [1, 3, 5]Verwenden Sie partition, wenn es genau zwei Buckets gibt, und group_by, wenn es viele sein können.
Aufgabe
MittelLies eine kommagetrennte Liste von name:score Einträgen (z. B. Alice:88,Bob:42,Charlie:75). Verwende group_by gefolgt von partition, um einen kleinen Bericht zu erstellen.
Schritte:
- Parse jeden Eintrag in ein
[name, score]Paar (score ist eine Ganzzahl) group_bynach dem ersten Buchstaben desname(großgeschrieben)- Für jede Buchstabengruppe, in alphabetischer Reihenfolge,
partitiondie Einträge in bestehend (score >= 60) und nicht bestehend, und gib dann eine Zeile pro Gruppe aus:
<LETTER>: pass=<names_passing_joined_by_comma> fail=<names_failing_joined_by_comma>Innerhalb jeder Gruppe erscheinen die Namen in ihrer ursprünglichen Reihenfolge. Wenn eine Seite keine Namen hat, lass sie leer (z. B. fail=).
Für die Eingabe Alice:88,Adam:42,Bob:75,Beth:55,Cara:90 lautet die Ausgabe:
A: pass=Alice fail=Adam
B: pass=Bob fail=Beth
C: pass=Cara fail=Spickzettel
group_by teilt eine Sammlung in einen Hash auf, der nach dem Ergebnis des Blocks indiziert ist:
words = ["hi", "hello", "yo"]
by_length = words.group_by { |w| w.length }
# {2=>["hi", "yo"], 5=>["hello"]}partition teilt in genau zwei Arrays auf (übereinstimmend und nicht übereinstimmend):
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
# evens => [2, 4], odds => [1, 3, 5]Verwenden Sie partition für zwei Kategorien, group_by für viele.
Probier es selbst
entries = gets.chomp.split(",").map do |s|
name, score = s.split(":")
[name, score.to_i]
end
# TODO: nach erstem Buchstaben gruppieren (groß), jede Gruppe nach score >= 60 aufteilen,
# 'X: pass=... fail=...' in alphabetischer Reihenfolge der Buchstaben ausgeben
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Logik & Programmfluss
1Strings im Detail
String-Methoden im ÜberblickString-InterpolationIterieren über StringsSplit und JoinRückblick – String Weaver4Blöcke, Procs & Lambdas
Was ist ein Block?do..end vs. geschweifte KlammernDas yield-SchlüsselwortBlock-ParameterProcs und LambdasZusammenfassung – Eigener Iterator7Hashes Teil 2
Hash.new mit StandardwertenIterieren über HashesVerschachtelte HashesZusammenführen und TransformierenRückblick – Häufigkeitszähler10Projekt - Studentenverwaltung
ProjektübersichtStudent hinzufügen5Enumerable-Kraftpaket
Select und RejectMap-VerkettungReduce / Injectcount, all?, any?, none?group_by und partitionsort_by, min_by, max_byZusammenfassung – Data Pipeline8Fortgeschrittene Entscheidungslogik
Case mit Klassen & RegexMulti-Value whenTernärer OperatorInline if / unlessRückblick – Noten-Klassifizierer