Слияние и преобразование
Часть раздела Логика и управление потоком путешествия по 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}Задание
СреднеДаны два хеша корзин: monday и tuesday, каждый из которых сопоставляет название товара (строку) с его количеством (целым числом). Магазину нужен нормализованный итог за два дня.
Создайте один итоговый хеш, выполнив следующие действия:
- Используйте
mergeдля объединения двух хешей с блоком, чтобы для ключей, присутствующих в обоих хешах, их количества суммировались (а не перезаписывались) - Примените
transform_keys(&:to_sym)к результату, чтобы ключи стали символами - Используйте
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
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Строки в деталях
Обзор методов строкИнтерполяция строкИтерация по строкамSplit и JoinИтоги — String Weaver4Блоки, Proc и лямбды
Что такое блок?do..end против фигурных скобокКлючевое слово yieldПараметры блокаProc и лямбдыИтоги: пользовательский итератор7Хеши. Часть 2
Hash.new со значениями по умолчаниюИтерация по хешамВложенные хешиСлияние и преобразованиеИтоги — счетчик частоты10Проект — Учёт студентов
Обзор проектаДобавить студента2Диапазоны
Что такое диапазон?Методы диапазоновДиапазоны в Case / WhenПовторение — практика по диапазонам5Мощь Enumerable
Select и RejectЦепочки MapReduce / Injectcount, all?, any?, none?group_by и partitionsort_by, min_by, max_byИтоги — Data Pipeline8Продвинутые условные конструкции
Case с классами и RegexМножественные значения в whenТернарный операторОднострочные if / unlessПовторение: Классификатор оценок