Monday, March 28, 2011

Picking Up Some Ruby

I'm currently spending some spare hacking time by making my way through Seven Languages in Seven Weeks. Conveniently, it starts out with Ruby, which happens to be a language I've been looking to dive into for quite some time now. There's a question and task in the book that asks for a way to convert from a hash to an array. This is pretty simple as hashes have a "to_a" method. As an example, take the following hash:

aHash = {"a"=>100, "b"=>200, "c"=>300, "d"=>400}
=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}

Converting this to an array results in the following:

aArray = aHash.to_a
=> [["a", 100], ["b", 200], ["c", 300], ["d", 400]]

Now, going the other direction is a bit more complicated as there doesn't seem to be a "to_h" method to convert from an array to a hash. By using the "inject" method, this is what I've come up with:

aArray.inject({}) {|a,b| a[b[0]]=b[1]; a}

I pass an empty hash as an argument to the inject method, which is the initial value for "a." Since "b" is the array of arrays, the values can be accessed via the bracket [] method and used to assign a key/value pair for the hash. Ruby's dynamic nature means we don't have to worry about initializing the hash size up front as this is all handled by the Ruby interpreter at runtime. Finally, there's a bit of trickery after the semi-colon. Every expression in Ruby returns a value, so by having the last value of our code block be the hash "a," we're able to prime the next value for "a" by doing this, thereby allowing us to incrementally build our hash.

A more visual way of seeing this in action is as follows:

aHash.to_a.inject({}) {|a,b| a[b[0]]=b[1]; puts a.inspect; a}
{"a"=>100}
{"a"=>100, "b"=>200}
{"a"=>100, "b"=>200, "c"=>300}
{"a"=>100, "b"=>200, "c"=>300, "d"=>400}
=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}

I'm eager to hear feedback on this if anyone is willing to share.

~Mike

1 comment:

  1. You can also use the [] class method on Hash to create a hash from the array.
    a_hash = {"a"=>100, "b"=>200, "c"=>300, "d"=>400}
    a_array = a_hash.to_a
    new_hash = Hash[a_array]

    ReplyDelete