7

我的目标是创建一个用哈希初始化的对象,然后查询该对象以从该哈希中获取值。为了让事情更清楚,这里有一个粗略的例子来说明我的意思:

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

但是,如果我打算大量使用这种方法,那么当我只想访问一个哈希值时,这将大大降低我的性能。

对此有何建议?

4

3 回答 3

13

自从被问到已经有一段时间了,要更新答案。

在 ruby​​ 2.3.1 中测试

你有一个像这样的哈希:

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

问题问:

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

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

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

由于问题的标题具有误导性(它应该类似于:如何在带有键数组的嵌套哈希中获取值),这里是实际提出的问题的答案:

通过键数组获取 ruby​​ 哈希值

准备:

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

回答:

my_hash.values_at(*my_array) #returns [1,6]
于 2017-05-03T01:17:55.537 回答
4
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
于 2012-11-27T08:15:20.513 回答
-3

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

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

...返回“价值”。

于 2012-11-27T09:02:17.233 回答