Menu
Coddy logo textTech

Слияние и преобразование

Часть раздела Логика и управление потоком путешествия по Ruby на Coddy — урок 36 из 56.

Две операции встречаются при работе с хешами настолько часто, что в Ruby для них предусмотрены собственные методы.

merge объединяет два хеша в один новый. Если в обоих хешах есть одинаковый ключ, приоритет отдается значению из правого хеша:

defaults = { color: "red", size: "M" }
custom   = { size: "L" }
settings = defaults.merge(custom)
puts settings.inspect   # {color: "red", size: "L"}

Ни один из оригиналов не изменяется, merge возвращает новый хеш.

transform_values создает новый хеш с теми же ключами, но каждое значение пропускается через блок:

prices = { apple: 1, bread: 3 }
with_tax = prices.transform_values { |p| p * 1.2 }
puts with_tax.inspect   # {apple: 1.2, bread: 3.6}

А transform_keys делает то же самое для ключей, что полезно при преобразовании строк в символы или нормализации регистра:

{ "a" => 1, "B" => 2 }.transform_keys(&:upcase)
# {"A"=>1, "B"=>2}
challenge icon

Задание

Средне

Даны два хеша корзин: monday и tuesday, каждый из которых сопоставляет название товара (строку) с его количеством (целым числом). Магазину нужен нормализованный итог за два дня.

Создайте один итоговый хеш, выполнив следующие действия:

  1. Используйте merge для объединения двух хешей с блоком, чтобы для ключей, присутствующих в обоих хешах, их количества суммировались (а не перезаписывались)
  2. Примените transform_keys(&:to_sym) к результату, чтобы ключи стали символами
  3. Используйте transform_values для применения оптовой скидки 10%: каждое количество становится равным (qty * 9 / 10), используя целочисленную арифметику

Выведите итоговый хеш с помощью inspect.

Для данных по умолчанию вывод будет следующим:

{:apples=>9, :bread=>4, :milk=>5, :cheese=>1}

(Apples: 5 + 5 = 10, затем 9. Bread: 3 + 2 = 5, затем 4. Milk: 6 только в Monday → 5. Cheese: 2 только в Tuesday → 1.)

Шпаргалка

merge объединяет два хеша; при конфликте ключей побеждает значение из правого хеша:

defaults = { color: "red", size: "M" }
custom   = { size: "L" }
settings = defaults.merge(custom)
# {color: "red", size: "L"}

Передайте блок в merge для ручной обработки дублирующихся ключей:

a.merge(b) { |key, old_val, new_val| old_val + new_val }

transform_values возвращает новый хеш, в котором каждое значение пропущено через блок:

prices = { apple: 1, bread: 3 }
prices.transform_values { |p| p * 1.2 }
# {apple: 1.2, bread: 3.6}

transform_keys делает то же самое для ключей:

{ "a" => 1 }.transform_keys(&:upcase)  # {"A"=>1}
{ "a" => 1 }.transform_keys(&:to_sym)  # {a: 1}

Попробуйте сами

monday  = { "apples" => 5, "bread" => 3, "milk" => 6 }
tuesday = { "apples" => 5, "bread" => 2, "cheese" => 2 }

# TODO: использовать merge с блоком для суммирования перекрывающихся ключей, затем преобразовать ключи в символы,
#       затем применить * 9 / 10 к каждому значению, затем выполнить inspect
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Логика и управление потоком