Подтвердить что ты не робот

Хеши хэш-идиомы в Ruby?

Создание хэшей хэшей в Ruby позволяет использовать два (или более) размерных поиска. Однако при вставке необходимо всегда проверять, существует ли первый индекс в хеше. Например:

h = Hash.new
h['x'] = Hash.new if not h.key?('x')
h['x']['y'] = value_to_insert

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

h = Hash.new
h['x']['y'] = value_to_insert

Аналогично, при поиске значения, когда первый индекс еще не существует, было бы предпочтительным, если nil возвращается, а не получает метод undefined для ошибки [].

looked_up_value = h['w']['z']

Можно создать класс оболочки Hash, который имеет такое поведение, но существует ли в нем идиум Ruby для выполнения этой задачи?

4b9b3361

Ответ 1

Вы можете передать Hash.new функцию, которая выполняется, чтобы получить значение по умолчанию, если запрошенное значение еще не существует

h = Hash.new { |h, k| h[k] = Hash.new }

Конечно, это можно сделать рекурсивно.

/EDIT: Ничего себе, статья, отвечая на этот вопрос.

Для полноты здесь решение из статьи для произвольных хешей глубины:

hash = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))

Кредиты отправляются в Кент из Data Noise.

Ответ 2

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

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

((h ||= { })['w'] ||= { })['z']

Ответ 3

require 'xkeys'
h = {}.extend XKeys::Hash

h['x', 'y'] = value_to_insert
looked_up_value = h['w', 'z'] # nil

h[:foo, :bar, :baz, :else => 0] += 1