Ruby Hash of Array idioms

I often need a hash of arrays in Ruby. So for example, I can have:

months = {"Feb"=>["Article1", "Article2", "Article3"], 
          "Mar"=>["Article4", "Article5"]}

Now if I am reading through an array of articles, I can set up my hash like so:

class Article
  attr_accessor :name, :month

  def initialize(name, month)
    @name = name
    @month = month
  end
end

articles = [
  Article.new("Article1", "Feb"), 
  Article.new("Article2", "Feb"), 
  Article.new("Article3", "Feb"), 
  Article.new("Article4", "Mar"), 
  Article.new("Article5", "Mar"), 
]

months = {}
articles.each do |a|
  months[a.month] ||= []
  months[a.month] << a.name
end

p months

This works great. For each article, we set a specific hash key to an empty array, but only if it is currently nil. That's what this does:

  months[a.month] ||= []

Then we add the article's name to the array:

  months[a.month] << a.name

There are more ways of doing that which might be better. You can combine the two lines:

months = {}
articles.each do |a|
  (months[a.month] ||= [])<< a.name
end

Another way is to provide a default for new hash values. When we create the hash (months = {}), we can specify a block which Ruby will use to generate default values in the hash. This makes things nicer:

months = Hash.new{|h, k| h[k] = []}
articles.each do |a|
  months[a.month] << a.name
end

Also, this way is a bit faster, since theoretically we are not testing each hash element for emptiness each time we add a value to the array. A benchmark does indeed show it to be slightly faster - though you need truly huge arrays to see any difference.

Metadata

Home

This is the website of Leslie Viljoen. I am a Disciple, Husband, Dad, Programmer, Gamer, Geek, Writer, Biker, Gardner. Perhaps even in that order. I currently live in Auckland, New Zealand.

Leslie

In 2011 I moved to Auckland and began working for TrifectaGIS, writing mostly Ruby and Rails code. I love my work!

Comments are welcome! Contact me AT gmail, using the address "leslieviljoen".


2011

May

April

2008

May

February

2007

May

March


Darwin

Diabetes

Interactive Fiction

Meta

Ruby

Ubuntu


Relatives and Friends

My LiveJournal
Village Montessori School
Loading.Ready.Run