Файлы
Справка
Телеграм чат начинающих программистов. Общаемся и помогаем друг другу
Если ссылка не открывается, можно найти нас в поиске по чатам @rubyrush
или
пойти другим путем
В этом уроке мы расскажем вам о двух важных понятиях в программировании вообще и в Ruby в частности: ассоциативные массивы (их ещё часто называют «хэшами») и метки (или символы, «symbols»).
Ассоциативный массив — это тип данных, которые представляет собой набор пар «ключ» — «значение». Вот простой пример:
Name: Вадим
Surname: Венедиктов
City: Москва
В руби для работы с ассоциативными массивами используют интерфейс хеш-таблицы, поэтому мы будем часто называть ассоциативные массивы хэшами.
В руби хэш с массивом из примера выглядел бы так:
{
"name" => "Вадим",
"surname" => "Венедиктов",
"city" => "Москва"
}
Мы уже знакомы с обычными массивами. Можно сказать, что в обычных массивах «ключом» каждого элемента является его номер. То есть, чтобы вытащить нужный элемент из массива, достаточно знать его номер. Это не всегда удобно, ведь номер элемента в массиве ничего не говорит о назначении этого элемента.
Ассоциативные массивы наглядны, ими удобнее пользоваться, когда данные в массиве разнородны, каждый элемент, таким образом, приобретает свой смысл. Из кода становится понятно, для чего какие данные в составе массива используются. Также с помощью ассоциативных массивом очень удобно передавать в метод несколько значений, не заботясь об их порядке. Но об этом позже.
Чтобы начать пользоваться хэшами, давайте немного узнаем о том, как с ними работать в ruby:
Создать ассоциативный массив:
associative_array = {
"key1" => "value1",
"key2" => "value2"
}
Обратите внимание, что как в качестве ключей, так и в качестве значений мы используем строки.
Получить элемент по ключу key1
:
associative_array["key1"]
Добавить в хэш элемент с ключом key3
и значением value3
:
associative_array["key3"] = "value3"
Проверить, есть ли в хэше элемент с ключом key1
:
associative_array.key?("key1")
Удалить из хэша элемент с ключом key1
associative_array.delete("key1")
Получить массив (обычный) всех ключей хэша:
associative_array.keys
Вот вкратце самые часто используемые методы при работе с хэшами. Подробнее всегда можно прочитать в документации Ruby к классу Hash.
Давайте откроем нашу программу про героев и злодеев (мы писали её в качестве домашней задачи к уроку 12, можете скопировать её оттуда или взять из материалов к этому уроку) и перепишем её с использованием ассоциативных массивов.
Программа выводит на экран антагониста того героя, которого укажет пользователь:
puts "Врага какого персонажа вы хотите узнать?"
hero = STDIN.gets.chomp
case hero
when "Бэтмен"
then puts "Джокер!"
when "Шерлок Холмс"
then puts "Профессор Мориарти"
when "Буратино"
then puts "Карабас-Барабас"
when "Фродо Бэггинс"
then puts "Саурон"
when "Моцарт"
then puts "Сальери"
else
puts "Не удалось найти врага"
end
А теперь перепишем эту программу с использованием ассоциативных массивов вместо инструкции case
:
puts "Врага какого персонажа вы хотите узнать?"
# Объявили новый ассоциативный массив с парами герой-антигерой
heros_antiheros = {
"Бэтмен" => "Джокер",
"Холмс" => "Мориарти",
"Буратино" => "Карабас-Барабас",
"Фродо Бэггинс" => "Саурон",
"Моцарт" => "Сальери"
}
# Получили выбор пользователя
hero = STDIN.gets.chomp
# Выводим антигероя, находя нужный элемент в ассоциативном массиве
if heros_antiheros.has_key?(hero) # проверка на наличие ключа в хэше
puts "Враг этого героя: #{heros_antiheros[hero]}"
else
puts "Не удалось найти врага"
end
Обратите внимание, насколько понятнее и проще стал код нашей программы. Все пары герой-антигерой находятся в одном месте и их удобно просматривать, редактировать и добавлять новые.
Как и в массиве, в ассоциативном массиве в качестве значений могут лежать любые объекты. Ключом также могут быть любые объекты, но мы рекомендуем пока пользоваться только строками (или метками, о которых расскажем позже).
{
"number" => 42,
"string" => 'Я строка',
"file" => File.new('file.txt', 'r')
}
Хэши также, как и массивы, бывают вложенными:
{
"key" => "value",
"hash" => {
"inner_key" => "inner_value"
}
}
Будьте аккуратны, в отличие от массивов, где элементы всегда следуют друг за другом по порядку, в ассоциативных массивах порядок не фиксирован и зависит от реализации. В Ruby, начиная с версии 1.9, ключи идут в том порядке, в котором они были добавлены в массив. Но я на вашем месте не стал бы на это полагаться.
Давайте напишем программу-шпаргалку, которая показывает информацию о выбранном пользователем химическом элементе таблицы Менделеева.
Создайте в RubyMine новый проект mendeleev
и напишите в нём программу mendeleev.rb
:
# Таблица, где символу элемента соответствует фамилия его первооткрывателя
table = {
'H' => 'Кавендиш',
'He' => 'Локьер, Жансен, Рамзай',
'Li' => 'Арфведсон',
'Be' => 'Воклен',
'B' => 'Дэви и Гей-Люссак',
'C' => 'неизвестен',
'N' => 'Резерфорд',
'O' => 'Пристли и Шееле',
'F' => 'Муассан',
'Ne' => 'Рамзай и Траверс'
}
# продолжите таблицу сами по вкусу
# https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D1%85%D0%B8%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D1%85_%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D0%BE%D0%B2
# выводим пользователю что у нас есть — вместе с количеством элементов
puts "У нас всего элементов: #{table.keys.size}"
# сами элементы — массив ключей хэша table
puts table.keys
puts "О каком элементе хотите узнать?"
element = gets.chomp
# проверка — есть ли в хэше элемент, который спросил пользователь
if table.has_key?(element)
puts "Первооткрывателем этого элемента считается: #{table[element]}"
else
puts "Извините, про такой элемент мы еще не знаем."
end
Теперь, надеемся, вы понимаете, насколько удобны хэши в руби и почему ими все пользуются.
Метка (по англ. symbol) — это особый тип данных. Это что-то вроде переменной, которая не указывает ни на какой объект, а лишь гордо носит своё собственное имя, которое само по себе и играет роль объекта-индикатора.
ВНИМАНИЕ! Правильное название меток в Руби — Символы
Чтобы не вдаваться в глубокие подробности, скажем лишь, что метки часто используется в хешах, когда набор ключей заранее известен. Создавать ассоциативные массивы с метками в качестве ключей можно двумя способами.
{
key: value
}
{
:key => value
}
Первый вариант более современный. Символы это очень мощный инструмент и без него современный рубист не представляет себе жизни.
Например, мы использовали их в ассоциативном массиве, когда передавали параметры
в метод Pony.mail
в программе для отправки почты из уроков про гемы.
Pony.mail({
:subject => "Привет из программы на руби!", # задаем тему письма
:body => body, # задаем содержимое письма, его тело
:to => send_to, # кому отправить письмо
:from => my_mail, # наш обратный адрес, от кого письмо
:via => :smtp,
:via_options => {
:address => 'smtp.mail.ru', # это хост, сервер отправки почты
:port => '465', # порт
:tls => true, # если сервер работает в режиме TLS
:user_name => my_mail, # используем наш адрес почты как логин
:password => password, # задаем введенный в консоли пароль
:authentication => :plain # "обычный" тип авторизации по паролю
}
})
Программа ожидает заранее определенный набор параметров и поэтому, чтобы это подчеркнуть, лучше в таких случаях использовать именно символы (метки) в качестве ключей хэша для параметров.
В этом уроке мы узнали о важном типе данных «Ассоциативный массив», который реализован в ruby с помощью хэшей, а в следующем уроке займёмся классами: узнаем, что такое наследование и как это помогает строить более сложные приложения.