Keren
Keren

Reputation: 217

returning value from nested hashes in Ruby

I'd like to return all the holiday symbols for which "BBQ" is a value (that is, :memorial_day and :fourth_of_july) in the following hash:

holiday_hash = 
      {
         :winter => {
           :christmas => ["Lights", "Wreath"],
           :new_years => ["Party Hats"]
         },
         :summer => {
           :fourth_of_july => ["Fireworks", "BBQ"]
         },
         :fall => {
           :thanksgiving => ["Turkey"]
         },
         :spring => {
           :memorial_day => ["BBQ"]
         }
       }

Here's my code:

def all_holidays_with_bbq(holiday_hash)
  holiday_hash.each do |season, holiday|
    season.each do |holiday|
      holiday.each do |supply|
        new_array = []
        if supply = "BBQ"
          new_array << supply.keys
        end
        new_array
      end
    end
  end
end

My code is returning this error:

NoMethodError:
        undefined method `each' for :winter:Symbol

Thanks!

Upvotes: 1

Views: 248

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110675

Your question has been answered by @KMRakibulIslam, but here's another way of doing it that I think is quite Ruby-like:

holiday_hash.values.
             flat_map(&:to_a).
             select { |_,a| a.include?("BBQ") }.
             map(&:first)
  #=> [:fourth_of_july, :memorial_day] 

Here are the steps:

a = holiday_hash.values
  #=> [{:christmas=>["Lights", "Wreath"], :new_years=>["Party Hats"]},
  #    {:fourth_of_july=>["Fireworks", "BBQ"]}, {:thanksgiving=>["Turkey"]},
  #    {:memorial_day=>["BBQ"]}] 
b = a.flat_map(&:to_a)
  #=> [[:christmas, ["Lights", "Wreath"]],
  #    [:new_years, ["Party Hats"]],
  #    [:fourth_of_july, ["Fireworks", "BBQ"]],
  #    [:thanksgiving, ["Turkey"]],
  #    [:memorial_day, ["BBQ"]]] 
c = b.select { |_,a| a.include?("BBQ") }
  #=> [[:fourth_of_july, ["Fireworks", "BBQ"]],
  #    [:memorial_day, ["BBQ"]]] 
c.map(&:first)
  #=> [:fourth_of_july, :memorial_day] 

Upvotes: 0

K M Rakibul Islam
K M Rakibul Islam

Reputation: 34338

Problem:

You are getting this error:

NoMethodError:
        undefined method `each' for :winter:Symbol

because you called .each on a symbol: season.each do |holiday| where season is a symbol. Instead, you should iterate over the hash elements like this: holiday_hash[season].each do |key, values| . . .

Solution:

You need to change your all_holidays_with_bbq method to the following to fix the issue:

def all_holidays_with_bbq(holiday_hash)
  new_array = []
  holiday_hash.keys.each do |season| # iterate over the keys(seasons) in your holiday_hash.
    holiday_hash[season].each do |key, value| # iterate over inner hash where season is the key.            
      new_array << key if value.include? 'BBQ'
    end
  end
  new_array
end

p all_holidays_with_bbq(holiday_hash)
# => [:fourth_of_july, :memorial_day]

Upvotes: 2

Related Questions