2012-03-12 12 views
2

でexistant私はハッシュのハッシュのハッシュの値になり、いくつかのRubyのコードを書いているかどうかを判断し....キーの連鎖がハッシュ

amz_price_info.raw["Offers"]["Offer"]["OfferListing"]["Price"]["FormattedPrice"] 

を、私はこれにアクセスしたいですコードの構造体が使用可能な場合にのみコード化します。現在のところ、私のコードは次のとおりです。

#amz_price_info.raw.class == Hashie::Mash 
    price = if amz_price_info.raw["Offers"] 
     if amz_price_info.raw["Offers"]["Offer"] 
      if amz_price_info.raw["Offers"]["Offer"]["OfferListing"] 
       if amz_price_info.raw["Offers"]["Offer"]["OfferListing"]["Price"] 
        if amz_price_info.raw["Offers"]["Offer"]["OfferListing"]["Price"]["FormattedPrice"] 
         amz_price_info.raw["Offers"]["Offer"]["OfferListing"]["Price"]["FormattedPrice"] 
        end 
       end 
      end 
     end 
    end 

私のコードはあまり冗長でないようにリファクタリングするにはどうすればよいですか?この方法は、パスが存在しない場合nilを返し、あなたがキーの任意の数のハッシュを下に検索できるようになります

答えて

5

これは、追加のメソッドを定義したり、ライブラリを導入したりしたくない場合の1つの方法です。レールで

amz_price_info.raw 
.fetch("Offers", {}) 
.fetch("Offer", {}) 
.fetch("OfferListing", {}) 
.fetch("Price", {}) 
.fetch("FormattedPrice", nil) 
3

def find_value(hash, keys) 
    keys.inject(hash.dup) do |prev, key| 
    prev && prev[key] ? prev[key] : nil 
    end 
end 

例:louismに触発

info = { "Offers" => { "Offer" => { 
     "OfferListing" => { "Price" => 
     { "FormattedPrice" => 10 }}}}} 

keys = %w[Offers Offer OfferListing Price FormattedPrice] 
puts find_value(info, keys)    # => 10 
puts find_value({"Offers" => {}}, keys) # => nil 
2

Iだろうこのようにしてください:

keys = %w[Offers Offer OfferListing Price FormattedPrice] 
price = amz_price_info.raw 
keys.each{|k| price = (price||{})[k]} 

編集:ニクラスのコメント

# This will return price or nil 
keys.inject(amz_price_info.raw) { |price, k| (price || {})[k] } 
+4

これはまた、{ 'keys.inject(amz_price_info.raw)のように書くことができます。 |価格、k | (価格|| {})[k]} ' –