Menu
Coddy logo textTech

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.

challenge icon

Desafio

Médio

Leia 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:

  1. Analise cada entrada em um par [name, score] (score é um número inteiro)
  2. Use group_by pela primeira letra do name do par (em maiúsculo)
  3. Para cada grupo de letras, em ordem alfabética, use partition nas 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
quiz iconTeste seus conhecimentos

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