How to collect a Hash from an Array

Updated . Posted . Visible to the public.

There are many different methods that allow mapping an Array to a Hash in Ruby.

Enumerable#index_by (any Rails)

users = User.all
users_by_id = users.index_by(&:id)
{
  1 => #<User id: 1, name: "Alice">,
  2 => #<User id: 2, name: "Bob"> 
}

In case of a duplicate, the last entry wins.

Enumerable#group_by (Ruby 1.8.7+)

Use group_by Show archive.org snapshot when duplicates are possible.
Hash values are always an Array of elements per group.

users = User.all
users_by_name = users.group_by(&:name)
{
  "Alice" => [#<User id: 1, name: "Alice">],
  "Bob" => [#<User id: 2, name: "Bob">]
}

Array#to_h (Ruby 2.1+)

Converts an Array of tuples into a Hash.
This is especially useful if the array's elements need to be transformed first.

users = User.all
user_names_by_id = users.map { |user| [user.id, user.name] }.to_h
{
  1 => "Alice",
  2 => "Bob"
}

Enumerable#index_with (Rails 6+)

To generate a hash where array elements become hash keys, and values are calculated from them, use index_with.

users = User.all
user_ids_by_user = users.index_with(&:name)
{
  #<User id: 1, name: "Alice"> => "Alice",
  #<User id: 2, name: "Bob"> => "Bob"
}

Legacy solution: collect_hash monkey patch

The attached initializer will let you create a hash from an array in a single method call.

  • Copy the attached initializer to config/initializers
  • All enumerables (arrays, sets, scopes, etc.) now have an additional method collect_hash
  • The method takes a block. The block is called for each element in the array and should return a 2-tuple where the first element is the key and the second element is the value.
  • A key/value entry is skipped when the block returns nil.

Example

The following will turn a list of User records into a hash where the keys are the users' ids and the values are the users' attribute hashes:

users = User.all
user_plans = users.collect_hash do |u|
  [u.id, u.attributes]
end
Henning Koch
Last edit
Arne Hartherz
Attachments
Keywords
list, map
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra dev (2010-09-14 11:31)