1 min read

Ruby each_with_object

Tranformations are common operations on Ruby collections, map and inject are useful but there's also another handy method
Ruby each_with_object
Photo by Thought Catalog / Unsplash

I see lots of code that looks like this (long-form blocks for readability):

collection = %w[red green blue black bronze]
result = [] # <<----- hmmmm, here is my problem

collection.each do |colour| 
  result << colour if colour.size >= 4
end

pp result

# ["green", "blue", "black", "bronze"]

I'd normally wince at the result object being manipulated by the each block and yell to use map and then a compact to get rid of nils. There is another way. Enter Enumerable#each_with_object.

collection = %w[red green blue black bronze]

# an object is passed to each iteration -------------++++++
# and it's created here -------------vv              vvvvvv
result = collection.each_with_object([]) do |colour, result| 
  result << colour if colour.size >= 4
  result # the return value here will be passed to the next iteration
end 

pp result

# ["green", "blue", "black", "bronze"]

This is neater and I can be sure that the result object doesn't suffer from any side-effects.