Mesclando e Transformando
Parte da seção Lógica e Fluxo do Journey de Ruby da Coddy — lição 36 de 56.
Duas operações surgem com tanta frequência ao trabalhar com hashes que o Ruby fornece a elas seus próprios métodos.
merge combina dois hashes em um novo. Quando ambos possuem a mesma chave, o valor da direita vence:
defaults = { color: "red", size: "M" }
custom = { size: "L" }
settings = defaults.merge(custom)
puts settings.inspect # {color: "red", size: "L"}Nenhum original é modificado, merge retorna um novo hash.
transform_values constrói um novo hash com as mesmas chaves, mas com cada valor passado por um bloco:
prices = { apple: 1, bread: 3 }
with_tax = prices.transform_values { |p| p * 1.2 }
puts with_tax.inspect # {apple: 1.2, bread: 3.6}E o transform_keys faz o mesmo para as chaves, sendo útil ao converter strings para símbolos ou normalizar a capitalização:
{ "a" => 1, "B" => 2 }.transform_keys(&:upcase)
# {"A"=>1, "B"=>2}Desafio
MédioDois hashes de carrinho são fornecidos: monday e tuesday, cada um mapeia o nome de um item (string) para uma quantidade inteira. A loja deseja um total normalizado de dois dias.
Produza um hash final ao:
- Fazer o
mergedos dois hashes com um bloco para que as chaves presentes em ambos tenham suas quantidades somadas (não sobrescritas) - Usar
transform_keys(&:to_sym)no resultado, para que as chaves se tornem símbolos - Usar
transform_valuespara aplicar um desconto de atacado de 10%: cada quantidade se torna(qty * 9 / 10)usando aritmética inteira
Imprima o hash final com inspect.
Para os dados padrão, a saída é:
{:apples=>9, :bread=>4, :milk=>5, :cheese=>1}(Apples: 5 + 5 = 10, depois 9. Bread: 3 + 2 = 5, depois 4. Milk: 6 apenas na Monday → 5. Cheese: 2 apenas na Tuesday → 1.)
Folha de consulta
merge combina dois hashes; quando as chaves conflitam, o valor da direita vence:
defaults = { color: "red", size: "M" }
custom = { size: "L" }
settings = defaults.merge(custom)
# {color: "red", size: "L"}Passe um bloco para merge para lidar com chaves duplicadas manualmente:
a.merge(b) { |key, old_val, new_val| old_val + new_val }transform_values retorna um novo hash com cada valor passado através de um bloco:
prices = { apple: 1, bread: 3 }
prices.transform_values { |p| p * 1.2 }
# {apple: 1.2, bread: 3.6}transform_keys faz o mesmo para as chaves:
{ "a" => 1 }.transform_keys(&:upcase) # {"A"=>1}
{ "a" => 1 }.transform_keys(&:to_sym) # {a: 1}Experimente você mesmo
monday = { "apples" => 5, "bread" => 3, "milk" => 6 }
tuesday = { "apples" => 5, "bread" => 2, "cheese" => 2 }
# TODO: merge-with-block para somar chaves sobrepostas, depois transformar chaves em símbolos,
# depois aplicar * 9 / 10 a cada valor, então inspecionar
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