Making Simple Methods for Data Structures

A great way to clean up your code and help clear your mind when looking through nested arrays and hashes is to make methods particular to your data structure for finding pieces of information. Let’s take a look at a great example.

Let’s say we have a Ruby hash with a series of nested hashes and arrays that looks like this:

holidays = {
  :new_years => {
    :date => "01/01",
    :supplies => ["booze","party hats"]
    },
  :valentines_day => {
    :date => "02/14",
    :supplies => ["flowers","booze","Marvin Gaye"]
    },
  :april_fools_day => {
    :date => "04/01",
    :supplies => ["whoppie cushion","fake news"]
    }, 
  :july_fourth => {
    :date => "07/04",
    :supplies => ["fire works","booze","BBQ"]
    },
  :thanksgiving => {
    :date => "fourth Thursday of November",
    :supplies => ["turkey","tofurkey","pumpkin pie","stuffing","booze"]
    }   
  }

This is a pretty basic data structure. We have a hash with five holidays. Each holiday has a hash with the date and an array of supplies used in the celebration.

Accessing the data in our holidays is pretty easy:

holidays.keys
 => [:new_years, :valentines_day, :april_fools_day, :july_fourth, :thanksgiving] 
holidays[:new_years].keys
 => [:date, :supplies] 
holidays[:new_years][:supplies]
 => ["booze", "party hats"] 

We can easily explore our data structure by repeating these processes. This mode of exploring the hash assumes we don’t know where everything is yet.

When we begin to ask the hash questions, it starts getting a little uglier. When we need to find things in different nests, methods become quite valuable. Here’s a few simple examples:

def date(holiday_name, data)
  data[holiday_name][:date]
end

def supplies(holiday_name, data)
  data[holiday_name][:supplies]
end

The first method “date”, simply returns the date of the a holiday. The second returns the supplies. When we have such a small data structure, it becomes easily debatable as to whether or not these save us any time. However even at this level, these methods become easier to read. This is a bit of opinion but take a look at these two examples:

supplies(:thanksgiving, holidays) 
#Supplies from Thanksgiving in holidays.

holidays[:thanksgiving][:supplies]
#Holidays has a key called Thanksgiving that has a key called supplies.

The difference is subtle and debatable. Let’s search for all the holidays that have “booze” as a supply. Here’s where it starts to become a worthwhile endeavor:

  holidays.select do |holiday_name, values| #select in holidays
    values[:supplies].include?("booze")     #hashes that have value inside of supplies
  end.keys                                  #but just the keys of those hashes
 => [:new_years, :valentines_day, :july_fourth, :thanksgiving] 

The code works! Hooray! It’s a pain to read and look at, but it works. It sure would be great if it was as easy to understand as either of the prior examples. Check out this alternative:


holidays_with_supply?("booze",holidays) 
 => [:new_years, :valentines_day, :july_fourth, :thanksgiving]

That makes sense! I can read that single line and know what to expect! Which holiday has “booze” as a supply? Let’s implement that method:

def holidays_with_supply?(supply, data)
  data.select do |holiday_name, values|
    values[:supplies].include?(supply)
  end.keys
end

On such a small piece of data, the importance of custom methods for looking over the structure seems trivial. As the size increases and the depth of nesting becomes greater, the time saved and clarity in code will become invaluable.

Thanks,
superandrew

Advertisements

4 thoughts on “Making Simple Methods for Data Structures

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s