group_by y partition
Parte de la sección Lógica y flujo del Journey de Ruby de Coddy — lección 25 de 56.
A veces querrás dividir una colección en lugar de filtrarla. Dos métodos cubren la mayoría de los casos.
group_by toma un bloque y devuelve un hash. Cada resultado único del bloque se convierte en una clave, mapeando a un array de los elementos que lo produjeron:
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 la forma más limpia de agrupar elementos en una sola pasada.
partition es la versión binaria: devuelve un par de arreglos, los elementos donde el bloque fue verdadero, y el resto:
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
puts evens.inspect # [2, 4]
puts odds.inspect # [1, 3, 5]Usa partition cuando hay exactamente dos grupos, y group_by cuando puede haber muchos.
Desafío
IntermedioLee una lista separada por comas de entradas name:score (por ejemplo, Alice:88,Bob:42,Charlie:75). Usa group_by seguido de partition para generar un pequeño informe.
Pasos:
- Analiza cada entrada en un par
[name, score](el puntaje es un entero) - Usa
group_bycon la primera letra delnamedel par (en mayúscula) - Para cada grupo de letras, en orden alfabético, usa
partitionpara dividir las entradas en aprobados (score >= 60) y reprobados, luego imprime una línea por grupo:
<LETTER>: pass=<names_passing_joined_by_comma> fail=<names_failing_joined_by_comma>Dentro de cada grupo, los nombres aparecen en su orden original. Si un lado no tiene nombres, déjalo vacío (por ejemplo, fail=).
Para la entrada Alice:88,Adam:42,Bob:75,Beth:55,Cara:90, la salida es:
A: pass=Alice fail=Adam
B: pass=Bob fail=Beth
C: pass=Cara fail=Hoja de referencia
group_by divide una colección en un hash cuya clave es el resultado del bloque:
words = ["hi", "hello", "yo"]
by_length = words.group_by { |w| w.length }
# {2=>["hi", "yo"], 5=>["hello"]}partition divide en exactamente dos arrays (los que coinciden y los que no):
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
# evens => [2, 4], odds => [1, 3, 5]Usa partition para dos grupos, group_by para muchos.
Pruébalo tú mismo
entries = gets.chomp.split(",").map do |s|
name, score = s.split(":")
[name, score.to_i]
end
# TODO: agrupar por la primera letra (mayúscula), particionar cada grupo por puntuación >= 60,
# imprimir 'X: pass=... fail=...' en orden alfabético de las letras
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Lógica y flujo
1Strings en profundidad
Visión general de los métodos de StringInterpolación de StringsIterar sobre StringsSplit y JoinRepaso - String Weaver4Bloques, Procs y Lambdas
¿Qué es un bloque?do..end vs llavesLa palabra clave yieldParámetros de bloqueProcs y LambdasResumen - Iterador personalizado7Hashes Parte 2
Hash.new con valores por defectoIteración de HashesHashes anidadosFusión y transformaciónResumen - Contador de frecuencia10Proyecto - Registros de Estudiantes
Descripción general del proyectoAgregar estudiante5Potencia de Enumerable
Select y RejectEncadenando MapReduce / Injectcount, all?, any?, none?group_by y partitionsort_by, min_by, max_byResumen - Data Pipeline