Хэши — один из самых важных и часто используемых типов данных в Ruby. Вы, наверное, уже знаете, что хэш также может называться словарем, содержащим набор уникальных ключей и связанных с ними значений. Их также иногда называют «ассоциативными массивами», потому что они действительно напоминают тип данных Array, за исключением того, что вместо индексов они используют любой тип объекта в качестве ссылки для значения. Это означает, что вы можете использовать целое число, строку, символ или даже логическое значение и массив в качестве ключа в вашем хэше/словаре.
Я собираюсь рассмотреть несколько способов создания хэша, некоторые из них более очевидны, а некоторые могут показаться вам немного неожиданными.
Первый и самый простой способ создания хэша – использование Hash.new.
moons = Hash.new => {} moons["Earth"] = ["Luna"] => ["Luna"] moons["Mars"] = ["Phobos", "Deimos"] => ["Phobos", "Deimos"] moons => {"Earth"=>["Luna"], "Mars"=>["Phobos", "Deimos"]}
Мы также можем использовать хеш-литералы (фигурные скобки) для одновременного создания и заполнения хэша данными:
moons = {"Earth"=>["Luna"], "Mars"=>["Phobos", "Deimos"]} => {"Earth"=>["Luna"], "Mars"=>["Phobos", "Deimos"]}
Другие необычные способы создания Hash включают передачу массива с четным числом элементов или массива массивов пар ключ-значение в Hash:
Hash["Earth", ["Luna"], "Mars", ["Phobos", "Deimos"]] => {"Earth"=>["Luna"], "Mars"=>["Phobos", "Deimos"]} Hash[["Earth", ["Luna"]], ["Mars", ["Phobos", "Deimos"]]] {["Earth", ["Luna"]]=>["Mars", ["Phobos", "Deimos"]]}
Вероятно, не так уж часто у вас будут данные для хэша, представленные в этом формате, но лучше иметь в виду как возможный вариант.
Создание хэша со значениями по умолчанию
Ruby позволяет нам создать пустой хэш и указать значения по умолчанию. Например, было бы неплохо указать по умолчанию, что каждый из наших ключей будет указывать на пустой массив.
moons = Hash.new([]) => {} moons["Earth"] => [] moons["Mars"] => []
Однако эта функция имеет подвох. Ruby не создает новый пустой объект-массив для каждого нового ключа в хеше, а указывает на один и тот же объект (в нашем случае пустой массив), значение которого было определено при инициализации хэша. Это означает, что как только мы изменим любую из записей хеша, созданных со значением по умолчанию, значение по умолчанию изменится. Взгляните на этот пример:
moons = Hash.new([]) => {} #moons record with key "Earth" is created with default value moons["Earth"] => [] #we modify moons["Earth"] to add it's moon moons["Earth"] << "Luna" => ["Luna"] #we attempt to create record with key "Mars" with default value moons["Mars"] << "Phobos" << "Deimos" => ["Luna", "Phobos", "Deimos"] #... and fail, because the default object was modified
При этом есть способ напрямую получить доступ и изменить значение по умолчанию, выполнив следующие действия:
moons.default => ["Luna"] moons.default = [] => []
Есть несколько полезных случаев для такого поведения значения по умолчанию, например, если это счетчик, который мы хотим увеличивать с каждой записью, однако есть ли способ просто создать новый пустой объект массива для каждой записи по умолчанию? Ответ — да, пройдя блок!
moons = Hash.new { |hash, key| hash[key] = [] } moons["Earth"] => [] moons["Earth"] << "Luna" => ["Luna"] moons["Mars"] => [] moons["Mars"] << "Phobos" << "Deimos" => ["Phobos", "Deimos]
Этот конструктор хэшей — довольно мощный инструмент для создания настраиваемых словарей!