What I'm aiming to do is to create an object which is initialized with a hash and then query this object in order to get values from that hash. To make things clearer here's a rough example of what I mean:
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"
I know I can perform iteration on the arguments list as in:
def get_value(*args)
value = @hash
args.each do |k|
value = value[k]
end
return value
end
But if I plan to use this method a lot this is going to degrade my performance dramatically when all I want to do is to access a hash value.
Any suggestions on that?
( tested in ruby 2.3.1 )
You have a hash like this:
my_hash = {:a => { :b => { :c => "value" } } }
The question asked:
my_hash.get_value(:a, :b, :c) # should return "value"
Answer: Use 'dig' instead of get_value, like so:
my_hash.dig(:a,:b,:c) # returns "value"
Since the title of the question is misleading (it should be something like: how to get a value inside a nested hash with an array of keys), here is an answer to the question actually asked:
Getting ruby hash values by an array of keys
Preparation:
my_hash = {:a => 1, :b => 3, :d => 6}
my_array = [:a,:d]
Answer:
my_hash.values_at(*my_array) #returns [1,6]
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
If you know the structure of the hash is always in that format you could just do:
holder[:a][:b][:c]
... returns "value".
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.