Iterating Through a Hash Where the First Key is an Array…of Hashes
By: Diana M.
Tags: Ruby, Coding Challenge, Coding Interviews

The next part of the method requires us to access the individual keys and values of each hash within the :birthday_count array. If we were able to pull out the initial information we wanted with birthdays[:birthday_count], how could we go about pulling the :month, :type and :factor keys? Try the following separately:

birthdays[:birthday_count].each do |bc|

puts bc[:month]

end

# => April, May, June, July birthdays[:birthday_count].each do |bc|

puts bc[:type]

end

#=> add, add, none, multiply birthdays[:birthday_count].each do |bc|

puts bc[:factor]

end

#=> 50, 10, , 2

Woo! We are successfully pulling the values of our keys. So now the question is, what the heck do we do with all of this?!

Let’s revisit the problem at hand. We want the base budget which has the value of 100, to be affected or not based on the value of type and factor of the respective month submitted to the method.

In other words, if the month is set to April, we want the budget to increase by 50, because the type is set to addition. Sounds like we need an if/else statement!

if bc[:month] == month

if bc[:type] == "multiply"

new_base_budget = base_budget * bc[:factor].to_f

elsif bc[:type] == "add"

new_base_budget = base_budget + bc[:factor].to_f

else

new_base_budget = base_budget

end

puts new_base_budget

end

What we’re saying here, is that if the key :month is equal to the argument we’re passing in (base_budget, birthdays, “July”), and if the value of the :type key of that month is set to “multiply”, do the following math to the base budget. Since we know how to access the value of :factor, we can multiply the base_budget by using that code “bc[:factor]”. Oh wait! The value of :factor is set to a string. We can use .to_i method to change it to an integer. However, what if one of these values was a decimal? Instead of .to_i, we can use .to_f. The “f” stands for float, which represents none whole numbers (i.e. decimals).

Next we write the condition of what we want the program to do if the value of the :type key is set to addition. Otherwise, nothing will happen to the base budget. The new logic of base_budget is stored in a variable, “new_base_budget”. After this condition statement is ended, we return the new_base_budget value. Let’s put it all together.

base_budget = 100

birthdays = {

birthday_count: [

{month: "April", type: "add", factor: "50"},

{month: "May", type: "add", factor: "10.5"},

{month: "June", type: "none"},

{month: "July", type: "multiply", factor: "2"}

]

} def adjust_birthday_budget(base_budget, birthdays, month)

birthdays[:birthday_count].each do |bc|

if bc[:month] == month

if bc[:type] == "multiply"

new_base_budget = base_budget * bc[:factor].to_f

elsif bc[:type] == "add"

new_base_budget = base_budget + bc[:factor].to_f

else

new_base_budget = base_budget

end

puts new_base_budget

end

end

end

=>#side note: you don't need the 'puts' but for Repl.it I did have to use it to see the output in the terminal. If there is no 'puts', a return is implicitly implied.

Try it out in Repl.it! Play around with the different months and see the results in the terminal.

There you have it, however, we’re not quite finished. The problem has been successfully solved, but can the solution be refactored? After reading up on Ruby’s ternary operator, I decided it could be. The following is how I refactored the above solution:

def adjust_birthday_budget(base_budget, birthdays, month)

birthdays[:birthday_count].each do |bc|

bc[:month] == month && bc[:type] == "multiply" ?

base_budget *= bc[:factor].to_f : base_budget

bc[:month] == month && bc[:type] == "add" ?

base_budget += bc[:factor].to_f : base_budget

end

puts base_budget

end adjust_birthday_budget(base_budget, birthdays, "July")

This took me some time and messing around with to figure out, so explaining the syntax will possibly be done in another post. However, if you plug this into Repl.it, you’ll see it works the same as the previous solution.

There you have it friends! I hope this was helpful, and am always open to feedback as I really want these posts to be supportive and educative to fellow programmers. To all aspiring software engineers/developers such as myself, do not get discouraged if you are unable to solve a problem during a coding interview. Keep practicing and never stop learning.

Thanks for reading ~