Ruby, iOS, and Other Development

A place to share useful code snippets, ideas, and techniques

All code in posted articles shall be considered public domain unless otherwise noted.
Comments remain the property of their authors.

2007-02-22

ArrayOfHashes

More often than I might have expected I wind up dealing with arrays of hashes. A lot of this comes from making JSON-RPC calls, incidentally, but that doesn't matter. The important thing is that I kept writing code like this:

values = foo.map{|x|x["bar"]}
...or worse...
some_values = foo.map{|x|x["bar"]}
other_values = foo.map{|x|x["baz"]}

I came to the conclusion that what I really wanted was a way to treat arrays of hashes in a special way, and that means mixing in a module! Here's the ArrayOfHashes module:

module ArrayOfHashes
  def transpose
    hash = {}
    each_with_index { |h,i| h.each { |k,v| (hash[k] ||= [])[i] = v } }
    hash
  end

  def [](key)
    map { |h| h[key] }
  end
end

It's pretty simple, actually. Array#transpose assumes it's an array of arrays, so this just overrides it with the assumption that it's an array of hashes. The result is a hash of arrays, generated in the spirit of the original Array#transpose. Overriding the [] operator is a little bit weirder, but it is (nearly) equivalent to using transpose[] without doing the full transpose.

So now those two examples become...

values = foo.extend(ArrayOfHashes)["bar"]
...and...
hash = foo.extend(ArrayOfHashes).transpose
some_values,other_values = hash["bar"],hash["baz"]
...respectively. Enjoy!

Labels: ,

0 Comments:

Post a Comment

<< Home