Hi, I'm

Jonathan Pike 👋

I'm a software developer in London, Ontario.


November 01, 2015 # permalink

I have heard it said1 that one is not a true Rubist until they learn Enumerable. To try and document what I’ve learned and keep it in my head, I am going to explain what I’ve learned here.

Today’s method: Map (or Collect, if you’re so inclined).

Let me preface the discussion of Map/Collect with a few notes:

  1. There is some distinction between the Enumerable module and Enumerable methods in other classes, such as array. An explanation can be found in this Stack Overflow post. Essentially, Enumerable objects need to call a function to get the next element (typically each), and Arrays are the most common collection, so Array#Map is optimized for performance. I’m going to be explaining the Array implementation of Map/Collect

  2. Ruby is awesomely friendly to programmers, and so a lot of methods are aliased to fit with whatever convention the programmer used prior to coming to Ruby. Another example is Inject/Reduce, which I will go into in a later post. Suffice it to say, you can use either Map or Collect and you will get the same result.

So, what is Map used for? Map is designed to iterate over an array and change each value. Take the following code, for example:

numbers = (1..10).to_a

# With Each and Push
new_numbers = []
numbers.each do |number|
  number = number ** 2
  new_numbers << number
# => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# With Map 
new_numbers = numbers.map { |number| number = number ** 2 }
# => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

I created an array of numbers from 1 - 10 on line 1, and I want to square each number in the array. You can see how Map does the same thing as looping over each number with each, squaring the number, and then pushing it to a new array. Map allowed me to compress 5 lines of code into 1.

Map does not modify the original array. If I did not assign the result to new_numbers, numbers would still be an array from 1 - 10. If you would like to modify the array in place, you can use Map!2.

One novel way of using Map that I’ve found is to use it to change the type of each item in an array. For example, if I have a string of numbers (str) and I would like to work on it as an array of integers, I would simply use the following: str.split(“”).map(&:to_i)

Super easy!

Map, like all of the Enumerable methods, is insanely useful, although complicated to get the hang of. Go and learn it by practicing!

  1. I don’t know who said it, I’ve just read it a lot!

  2. This is called a dangerous method because they change the state of an object that some other object may have referenced.