通过一组键获取ruby哈希值

时间:2021-01-11 21:17:23

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?

有什么建议吗?

3 个解决方案

#1


8  

To update the answer since it's been a while since it was asked.

(tested in ruby 2.3.1)

(在红宝石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:

答:使用'dig'而不是get_value,如下所示:

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

通过一组键获取ruby哈希值

Preparation:

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

Answer:

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

#2


4  

def get_value(*args)
  args.inject(@hash, &:fetch)
end


In case you want to avoid iteration at lookup (which I do not feel necessary), then you need to flatten the hash to be stored:

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  

If you know the structure of the hash is always in that format you could just do:

如果您知道哈希的结构始终采用该格式,您可以这样做:

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

... returns "value".

...返回“价值”。

#1


8  

To update the answer since it's been a while since it was asked.

(tested in ruby 2.3.1)

(在红宝石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:

答:使用'dig'而不是get_value,如下所示:

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

通过一组键获取ruby哈希值

Preparation:

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

Answer:

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

#2


4  

def get_value(*args)
  args.inject(@hash, &:fetch)
end


In case you want to avoid iteration at lookup (which I do not feel necessary), then you need to flatten the hash to be stored:

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  

If you know the structure of the hash is always in that format you could just do:

如果您知道哈希的结构始终采用该格式,您可以这样做:

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

... returns "value".

...返回“价值”。