/ / Отримання значень хеш-рубіну за допомогою масиву ключів - ruby-on-rails, ruby, масиви, хеш

Отримання рубінового хеш-значення за допомогою масиву ключів - ruby-on-rail, ruby, arrays, hash

Я маю на меті створити об'єктякий ініціалізується з хешем, а потім запитувати цей об’єкт, щоб отримати значення з цього хеша. Щоб зробити тут зрозумілішими речі, - це приблизний приклад того, що я маю на увазі:

class HashHolder
def initialize(hash)
@hash = hash
end

def get_value(*args)
# What are my possibilities here?
end
end

holder = HashHolder.new({:a => { :b => { :c => "value" } } } )
holder.get_value(:a, :b, :c) # should return "value"

Я знаю, що можу виконати ітерацію у списку аргументів, як у:

def get_value(*args)
value = @hash
args.each do |k|
value = value[k]
end
return value
end

Але якщо я планую багато використовувати цей метод, це призведе до різкого погіршення моєї продуктивності, коли все, що я хочу зробити, - це отримати доступ до хеш-значення.

Будь-які пропозиції з цього приводу?

Відповіді:

7 для відповіді № 1

Щоб оновити відповідь, оскільки пройшло деякий час, оскільки її задали.

(випробуваний на рубіні 2.3.1)

У вас такий хеш:

my_hash = {:a => { :b => { :c => "value" } } }

Задане запитання:

my_hash.get_value(:a, :b, :c) # should return "value"

Відповідь: Використовуйте "копати" замість get_value, наприклад:

my_hash.dig(:a,:b,:c) # returns "value"

Оскільки заголовок питання вводить в оману (він повинен бути чимось на зразок: як отримати значення всередині вкладеного хеша з масивом ключів), ось відповідь на фактично задане запитання:

Отримання значень хеш-рубіну за допомогою масиву ключів

Підготовка:

my_hash = {:a => 1, :b => 3, :d => 6}
my_array = [:a,:d]

Відповідь:

my_hash.values_at(*my_array) #returns [1,6]

4 для відповіді № 2
def get_value(*args)
args.inject(@hash, &:fetch)
end


Якщо ви хочете уникнути ітерації під час пошуку (що я не вважаю за потрібне), тоді вам потрібно вирівняти хеш для зберігання:

class HashHolder
def initialize(hash)
while hash.values.any?{|v| v.kind_of?(Hash)}
hash.to_a.each{|k, v| if v.kind_of?(Hash); hash.delete(k).each{|kk, vv| hash[[*k, kk]] = vv} end}
end
@hash = hash
end
def get_value(*args)
@hash[args]
end
end

-3 для відповіді № 3

Якщо ви знаєте, що структура хеша завжди знаходиться у такому форматі, ви можете просто зробити:

holder[:a][:b][:c]

... повертає "значення".