map transforms every element

Free preview 2 min to read

A method built to return something new

The last course set out each's job: run code once per element for its side effects, and hand back the same collection. map does the opposite job.

numbers = [1, 2, 3]
doubled = numbers.map { |n| n * 2 }
doubled   # => [2, 4, 6]
numbers   # => [1, 2, 3], untouched

map calls the block once per element, like each, but collects each value the block computes into a new array and returns it. numbers is left alone, the "returns new, doesn't mutate" pattern the arrays course showed for sort.

The result is always the same length as the original

words = ["cat", "elephant", "dog"]
lengths = words.map { |w| w.length }
lengths   # => [3, 8, 3]

Three words in, three numbers out. map never skips or adds an element, so the result lines up with the original: lengths[0] describes words[0], lengths[1] describes words[1], and so on.

What map's block returns matters

Here's the real difference from each. each throws the block's return value away. For map, that value is the point: it becomes the matching element of the new array.

numbers = [1, 2, 3]
numbers.each { |n| n * 2 }    # => [1, 2, 3], the *2 is discarded
numbers.map { |n| n * 2 }     # => [2, 4, 6], the *2 becomes the result

Same block and same input, but different return values, because the two methods treat the block's result differently.

Key takeaways

  • map collects each block result into a new array and leaves the original untouched.
  • The result always has the same length as the original, lined up position by position.
  • The block's return value becomes the new element; each discards it.
  • Use map when the goal is a transformed collection, not a side effect.
Lesson 1 of 7 · free

Keep going with lesson 2

map vs each

Choose each for side effects and map for a new collection, based on what happens to the block's result.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...