Posted 15 days ago. Visible to the public. Linked content. Auto-destruct in 45 days

Updated: How to collect a Hash from an Array

Examples for each case which should show the methods' differences more clearly.

Changes

  • There are many different methods that allow mapping an Array to a Hash in Ruby.
  • ## `Enumerable#index_by` (any Rails)
  • ```ruby
  • users = User.all
  • users_by_id = users.index_by(&:id)
  • ```
  • +```ruby
  • +{
  • + 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`](http://apidock.com/rails/Enumerable/group_by) when duplicates are possible.
  • Hash values are always an Array of elements per group.
  • ```ruby
  • users = User.all
  • users_by_name = users.group_by(&:name)
  • ```
  • +```ruby
  • +{
  • + "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.
  • ```ruby
  • users = User.all
  • user_names_by_id = users.map { |user| [user.id, user.name] }.to_h
  • ```
  • +```ruby
  • +{
  • + 1 => "Alice",
  • + 2 => "Bob"
  • +}
  • +```
  • ## `Enumerable#index_with` (Rails 6+)
  • -To generate a hash where values need to be calculated but array elements become hash keys, use `index_with`.
  • +To generate a hash where array elements become hash keys, and values are calculated from them, use `index_with`.
  • ```ruby
  • -[:foo, :bar].index_with(&:to_s)
  • -# => {foo: "foo", bar: "bar"}
  • +users = User.all
  • +user_ids_by_user = users.index_with(&:name)
  • +```
  • +```ruby
  • +{
  • + #<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:
  • ```ruby
  • users = User.all
  • user_plans = users.collect_hash do |u|
  • [u.id, u.attributes]
  • end
  • ```

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for unsupported versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2).

Owner of this card:

Avatar
Arne Hartherz
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev
This website uses short-lived cookies to improve usability.
Accept or learn more