Ruby Enumerable Methods

Recently, I have realized that there are many powerful enumerable methods in Ruby so I would like to introduce them in this post. I will keep adding contents as I learn more methods.

inject vs each_with_object

Building a new hash and mapping, you should consider using inject and each_with_object methods.

Let’s say we would like to return a hash of its correct length with given an array. So for example:

hash = ['ben', 'chris', 'mark']
puts get_string_lengths(hash)
# expected {"ben"=>3, "chris"=>5, "mark"=>4}

All versions below give the same result.

# solution 1
def get_string_lengths_v1(strings)
    strings.inject({}) do |hash, string|
        hash[string] = string.length
        hash
    end
end

# solution 2
def get_string_lengths_v2(strings)
    strings.inject({}) do |hash, string|
        hash.merge(string => string.length)
    end
end

# solution 3
def get_string_lengths_v3(strings)
    strings.each_with_object({}) do |string, hash|
        hash[string] = string.length
    end
end

puts get_string_lengths_v1(%w(ben chris mark))
puts get_string_lengths_v2(%w(ben chris mark))
puts get_string_lengths_v3(%w(ben chris mark))

For the first solution, inject requires memoized value for subsequent block calls, so I returned the hash object in the block. I felt it is less convenient so I tried using merge method in the second solution because it returns a hash. Lastly, I used each_with_object method and I felt more convenient.

You cannot use immutable objects for each_with_object method.

(1..5).each_with_object(0) do |item, sum|
  sum += item
end
# => 0 since numbers are immutable

In this case, inject method is used for immutable objects which return a new value.

(1..5).inject(:+)

Taeyang Lee

Taeyang Lee
I really enjoy taking on tasks which are out of my comfort zone and using them as a great way to learn the necessary tools to complete it.

Monads

Published on December 17, 2018

Functors

Published on December 16, 2018