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"

回答:次のように、get_valueの代わりに「dig」を使用してください。

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]
于 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 に答える