Search code examples
rubymethodsreturn-valueenumerable

Ruby: cleaner returns from loop iteration methods


I find that I frequently have methods that iterate through an enumerable in order to return a different enumerable or a hash. These methods almost always look like this simplistic example:

  def build_hash(array)
    hash = {}
    array.each do |item|
      hash[ item[:id] ]= item
    end
    hash
  end

This approach works works, but I've often wondered if there's a cleaner way to do this, specifically without having to wrap the loop in a temporary object so that the return is correct.

Does anyone know of an improved and/or cleaner and/or faster way to do this, or is this pretty much the best way?


Solution

  • Here are a few ways, considering your specific example

    arr = [{:id => 1, :name => :foo}, {:id => 2, :name => :bar}]
    
    Hash[arr.map{ |o| [o[:id], o] }]
    arr.each_with_object({}){ |o, h| h[o[:id]] = o }
    arr.reduce({}){ |h, o| h[o[:id]] = o; h }
    arr.reduce({}){ |h, o| h.merge o[:id] => o }
    
    # each of these return the same Hash
    # {1=>{:id=>1, :name=>:foo}, 2=>{:id=>2, :name=>:bar}}