Хэш таблица и сет

Ранее мы поговорили поговорили о такой структуре данных как массив. Настало время поговорить про остальные базовые структуры данных

Хэш

Хэш таблица (еще она называется Hash map в других ЯП) - структура данных, хранящая в себе сразу 2 элмента - ключ и значение. Ключ - уникальный, значение - нет.

# создание пустой хэш таблицы
hash = Hash.new
# Упрощенная запись
hash = {}
# Способ создания хэш таблицы с заранее созданным содержанием
hash = Hash['key_1' => 'value_1', 'key_2' => 'value_2', 'key_1' => 'value_3']
# Упрощенная запись через кавычки
hash = {'key_1' => 'value_1', 'key_2' => 'value_2', 'key_1' => 'value_3'}
# Начиная с ruby 1.9 появилась возможность записывать ключ - значение через двоеточие. 
# Данный вариант записи стоит считать наиболее предпочтительный, вместо Hash[...] или использования => 
# так как при записи key: value, key приводится к символу, о котором мы поговорим в следующем уроке
hash = {'key_1': 'value_1', 'key_2': 'value_2', 'key_1': 'value_3'}
# Обрати внимание, что key_1 содержится только один раз, не смотря на то, что мы его объявляли дважды
# И значение содержится от последней объявляенной пары с таким же ключом
puts hash # = {'key_1' => 'value_3', 'key_2' => 'value_2'}

Легче всего представлть хэш таблицу как словарь. Если открыть любой словарь, то мы увидим в нем слово и его перевод/ы. При этом один и тот же перевод, может относиться к различным словам. Давайте попробуем реализовать такой словарь с помощью Hash:

Теперь стоит обсудить как изменять хэш таблицу:

Давайте посмотрим на особенность итерации хэша в цикле:

Сет

Настало поговорить про Set. Set - это нечто среднее между массивом и хэш таблицей. Сет - это тот же самый Hash, но без значений, только ключи.

Сравнение Set vs Array

Хоть базовые алгоритмы мы изучим в дальнейшем, но сейчас важно понимать в чем приемущество Set по сравнению с Array

Рассмотрим такой метод как .include? который присутствует и у Array и у Set

Попробуйте запустить код у себя локально и сравнить время работы одних и тех же методов у разных структур.

Проверили ? Да, разница впечатляющая. Все дело в особенности работы этих структур. Метод .unclude? у Array обходит все свои элементы и проверяет на соотвествие (==). Сначала 1 элемент, потом 2, потом 3 и тд. Чем больше элементов, тем дольше может работать unclude?.

Семейство хэш структур одновременно знают все о своих ключах. Даже если увеличить размер структуры в десять раз или в сотню, скорость от этого не меняется. Это называется константное время, когда скорость доступа к элементу не меняется при изменении размера самой структуры. Так как Set это тот же самый Hash, но без значений, то правило и применимо для него.

Возможно у вас появилась мысль а зачем тогда испоьзовать массив если есть сет ? Всему свое место. Set - отлично, когда нам целенаправлено нужно использовать уникальность знчений. Если посмотреть на разницу во времени на добавление элементов, то заметим внушительный перевес по скорости у массива.

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

  • У массива доступ к элементу по значению прямо зависит от размера самого массива

  • У хэш таблицы и сета доступ по ключу не зависит от размера структуры, за счет чего действие происходит мгновенно

Задание key_vs_value

У Hash также имеются методы value?, который проверяет на наличие значения, и key?, который проверяет на наличие ключ.

  • Перепишите пример со сравнением скорости массива и сета на сравнение скорости метода value? и key?, переписав также метод добавления элементов, где ключ и значение это одно и тоже значение для хэш таблицы

  • Расскажите о выводах которые вы можете сделать касаемо этих методов, после изучения полученных результатов

Задание email_checker

Задание на умение работать сетом.

  • Напишите программу, в которой будет храниться перечень адресов электронной почты. Адреса можно добавлять через консоль командой ADD и печатать весь список командой LIST.

  • Программа должна проверять корректность вводимых email’ов (вспоминаем прошлый урок) и печатать сообщение об ошибке при необходимости.

Принцип работы команд

  • LIST — выводит список электронных адресов.

  • ADD — проверяет и, если формат адреса верный, добавляет в множество.

Примеры команд

  • LIST

  • ADD ruby_course@rambler.ru

Команды вводятся одной строкой пользователем в консоль.

Задание phone_book

Задание на умение работать с хэш таблицей.

  • Напишите программу, которая будет работать как телефонная книга:

    • Если пишем новое имя, программа просит ввести номер телефона и запоминает его. Если новый номер телефона — просит ввести имя и также запоминает.

    • Если вводим существующее имя или номер телефона, программа выводит всю информацию о контакте.

    • При вводе команды LIST программа печатает в консоль список всех абонентов в алфавитном порядке с номерами.

  • Определяйте имя и телефон с помощью регулярных выражений.

  • Подумайте, что выбрать в качестве ключа и значения для хэш таблицы, выберите лучший вариант по вашему мнению. Опишите, какие минусы и плюсы видите в вашем выборе.

Last updated