The cleanest way to create a hash from an array

It seems I often came across this. I need to build a hash from an array using the attribute of each object in the array as a key.

Suppose I need an example hash, uses ActiveRecord objects bound by their identifiers. The usual way:

ary = [collection of ActiveRecord objects] hash = ary.inject({}) {|hash, obj| hash[obj.id] = obj } 

Another way:

 ary = [collection of ActiveRecord objects] hash = Hash[*(ary.map {|obj| [obj.id, obj]}).flatten] 

Dream: I could and could create it myself, but is there anything in Ruby or Rails that it will be?

 ary = [collection of ActiveRecord objects] hash = ary.to_hash &:id #or at least hash = ary.to_hash {|obj| obj.id} 
+26
arrays ruby ruby-on-rails hash
Jan 05 '09 at 10:44
source share
5 answers

ActiveSupport already has a method that does this.

 ['an array', 'of active record', 'objects'].index_by(&:id) 

And just for the record, here's the implementation:

 def index_by inject({}) do |accum, elem| accum[yield(elem)] = elem accum end end 

Which could be reorganized (if you are desperate for a one-line interface):

 def index_by inject({}) {|hash, elem| hash.merge!(yield(elem) => elem) } end 
+48
Jan 05 '09 at 12:17
source share

the shortest?

 # 'Region' is a sample class here # you can put 'self.to_hash' method into any class you like class Region < ActiveRecord::Base def self.to_hash Hash[*all.map{ |x| [x.id, x] }.flatten] end end 
+8
Apr 14 '13 at 22:44
source share

You can add to_hash to Array yourself.

 class Array def to_hash(&block) Hash[*self.map {|e| [block.call(e), e] }.flatten] end end ary = [collection of ActiveRecord objects] ary.to_hash do |element| element.id end 
+5
Jan 05 '09 at 11:52
source share

If someone got a simple array

 arr = ["banana", "apple"] Hash[arr.map.with_index.to_a] => {"banana"=>0, "apple"=>1} 
+4
Mar 10 '17 at 14:15
source share

Install the Ruby Facets Gem and use Array.to_h .

0
Jan 05 '09 at 17:14
source share



All Articles