Map
The map pattern is similar to the for-each pattern, but instead of achieving some side effect for each item, the loop transforms each item into a new item. Perhaps each string is turned into a lowercase version of the same text. Perhaps each number is converted to some other number. Perhaps each image is resized to some new image. All the new items are collected together in a new array that has the exact same size as the original. Visually, the map pattern performs this operation:
Map is implemented as in the following pseudocode:
class Collection
items = ...
function map(transformOne)
newItems = new array(items.size)
for i in 0 to items.size
newItems[i] = transformOne(items[i], i)
return newItems
Ruby implements the map pattern in the map
method of its Array
class. With map
, you may transform your arrays without the pageantry of loops:
lengths = words.map { |word| word.length }
kilometers = miles.map { |mile| mile * 1.60934 }
commands = commands.map { |command| command.downcase }
If an index is needed in order to transform an item, Ruby provides a with_index
method that may be called on the iterator that map
returns. This script turns an array of rules into an array of numbered rules using indices:
numbered_rules = rules.map.with_index do |rule, i|
"#{i + 1}. #{rule}"
end
We will examine how other languages have implemented the map pattern later on when we discuss lambdas and closures. Python has its own map
function, but the community favors transforming one list into another using a list comprehension:
kilometers = [mile * 1.60934 for mile in miles]
Haskell supports both list comprehensions and map
, but the community tends to favor map
for its consistency with the rest of the language.