group_by e partition
Parte da seção Lógica e Fluxo do Journey de Ruby da Coddy — lição 25 de 56.
Às vezes você quer dividir uma coleção em vez de filtrá-la. Dois métodos cobrem a maioria dos casos.
group_by recebe um bloco e retorna um hash. Cada resultado único do bloco torna-se uma chave, mapeando para um array dos elementos que o produziram:
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"]}É a maneira mais limpa de agrupar itens em uma única passagem.
partition é a versão binária: ele retorna um par de arrays, os elementos onde o bloco foi verdadeiro, e o restante:
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
puts evens.inspect # [2, 4]
puts odds.inspect # [1, 3, 5]Use partition quando houver exatamente dois buckets, group_by quando puder haver muitos.
Desafio
MédioLeia uma lista separada por vírgulas de entradas name:score (ex: Alice:88,Bob:42,Charlie:75). Use group_by seguido de partition para produzir um pequeno relatório.
Passos:
- Analise cada entrada em um par
[name, score](score é um número inteiro) - Use
group_bypela primeira letra donamedo par (em maiúsculo) - Para cada grupo de letras, em ordem alfabética, use
partitionnas entradas em aprovados (score >= 60) e reprovados, então imprima uma linha por grupo:
<LETTER>: pass=<names_passing_joined_by_comma> fail=<names_failing_joined_by_comma>Dentro de cada grupo, os nomes aparecem em sua ordem original. Se um lado não tiver nomes, deixe-o vazio (ex: fail=).
Para a entrada Alice:88,Adam:42,Bob:75,Beth:55,Cara:90, a saída é:
A: pass=Alice fail=Adam
B: pass=Bob fail=Beth
C: pass=Cara fail=Folha de consulta
group_by divide uma coleção em um hash cujas chaves são o resultado do bloco:
words = ["hi", "hello", "yo"]
by_length = words.group_by { |w| w.length }
# {2=>["hi", "yo"], 5=>["hello"]}partition divide em exatamente dois arrays (correspondentes e não correspondentes):
evens, odds = [1, 2, 3, 4, 5].partition { |n| n.even? }
# evens => [2, 4], odds => [1, 3, 5]Use partition para dois grupos, group_by para muitos.
Experimente você mesmo
entries = gets.chomp.split(",").map do |s|
name, score = s.split(":")
[name, score.to_i]
end
# TODO: agrupar pela primeira letra (maiúscula), particionar cada grupo por score >= 60,
# imprimir 'X: pass=... fail=...' em ordem alfabética das letras
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Lógica e Fluxo
1Strings a Fundo
Visão Geral de Métodos de StringInterpolação de StringsIterando sobre StringsSplit e JoinRecapitulação - String Weaver4Blocos, Procs e Lambdas
O que é um Bloco?do..end vs ChavesA palavra-chave yieldParâmetros de BlocoProcs e LambdasRecapitulação - Iterador Customizado7Hashes Parte 2
Hash.new com Valores PadrãoIterando em HashesHashes AninhadosMesclando e TransformandoRecapitulação - Contador de Frequência10Projeto - Registros de Alunos
Visão Geral do ProjetoAdicionar Aluno2Intervalos
O que é um Intervalo?Métodos de IntervaloIntervalos em Case / WhenRecapitulação - Prática com Intervalos5O Poder do Enumerable
Select e RejectEncadeando o MapReduce / Injectcount, all?, any?, none?group_by e partitionsort_by, min_by, max_byRecapitulação - Data Pipeline