I seem to run into this very often. I need to build a Hash from an array using an attribute of each object in the array as the key.
Lets say I need a hash of example uses ActiveRecord objecs keyed by their ids Common 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 Way: I could and might create this myself, but is there anything in Ruby or Rails that will this?
ary = [collection of ActiveRecord objects] hash = ary.to_hash &:id #or at least hash = ary.to_hash {|obj| obj.id}
The to_h method is defined in the array class. It works to convert an array to a hash in the form of key-value pairs. The method converts each nested array into key-value pairs. The method also accepts a block.
hashCode(Object[]) method returns a hash code based on the contents of the specified array. If the array contains other arrays as elements, the hash code is based on their identities rather than their contents. For any two arrays a and b such that Arrays.
With arrays, the key is an integer, whereas hashes support any object as a key. Both arrays and hashes grow as needed to hold new elements. It's more efficient to access array elements, but hashes provide more flexibility.
Ruby | Array to_h() function Array#to_h() : to_h() is a Array class method which returns the result of interpreting ary as an array of [key, value] pairs. Syntax: Array.to_h() Parameter: Array. Return: the result of interpreting ary as an array of [key, value] pairs.
There is already a method in ActiveSupport 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 have been refactored into (if you're desperate for one-liners):
def index_by inject({}) {|hash, elem| hash.merge!(yield(elem) => elem) } end
a shortest one?
# '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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With